Sprache Deutsch Language English

Script Dokumentation LS 2015 - Fillable (Patch 1.3)

Script Dokumentation Übersicht

scripts/vehicles/specializations/Fillable.lua

Copyright (c) 2008-2015 GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de
1--
2-- Fillable
3-- This is the specialization for fillable vehicles, such as trailers or sprayers
4--
5-- @author Stefan Geiger
6-- @date 22/07/10
7--
8-- Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved.
9
10source("dataS/scripts/vehicles/specializations/FillActivatable.lua");
11
12Fillable = {};
13
14Fillable.NUM_FILLTYPES = 0;
15Fillable.FILLTYPE_UNKNOWN = 0;
16Fillable.FILLTYPE_START_TOTAL_AMOUNT = 500000;
17
18Fillable.fillTypeNameToInt = {}
19Fillable.fillTypeIntToName = {}
20
21Fillable.fillTypeIndexToDesc = {}
22Fillable.fillTypeNameToDesc = {}
23Fillable.economyFillTypes = {};
24
25Fillable.defaultFillPlaneMaterial = nil;
26Fillable.defaultFillIconMaterial = nil;
27
28Fillable.MATERIAL_TYPE_FILLPLANE = 1;
29Fillable.MATERIAL_TYPE_ICON = 2;
30Fillable.MATERIAL_TYPE_UNLOADING = 3;
31Fillable.MATERIAL_TYPE_SMOKE = 4;
32Fillable.MATERIAL_TYPE_STRAW = 5;
33Fillable.MATERIAL_TYPE_CHOPPER = 6;
34
35Fillable.defaultMaterials = {};
36
37Fillable.fillTypeNameToInt["unknown"] = Fillable.FILLTYPE_UNKNOWN;
38Fillable.fillTypeIntToName[Fillable.FILLTYPE_UNKNOWN] = "unknown";
39
40Fillable.sendNumBits = 6;
41
42function Fillable.registerFillType(name, nameI18N, pricePerLiter, partOfEconomy, hudOverlayFilename, hudOverlayFilenameSmall, massPerLiter, maxPhysicalSurfaceAngle)
43 local key = "FILLTYPE_"..string.upper(name);
44 if Fillable[key] == nil then
45 if Fillable.NUM_FILLTYPES >= 64 then
46 print("Error: Fillable.registerFillType too many fill types. Only 64 fill types are supported");
47 return;
48 end;
49 Fillable.NUM_FILLTYPES = Fillable.NUM_FILLTYPES+1;
50 Fillable[key] = Fillable.NUM_FILLTYPES;
51 Fillable.fillTypeNameToInt[name] = Fillable.NUM_FILLTYPES;
52 Fillable.fillTypeIntToName[Fillable.NUM_FILLTYPES] = name;
53
54 local desc = {};
55 desc.name = name;
56 desc.nameI18N = nameI18N;
57 if desc.nameI18N == nil then
58 desc.nameI18N = name;
59 if g_i18n:hasText(desc.nameI18N) then
60 desc.nameI18N = g_i18n:getText(name);
61 end
62 end
63 desc.index = Fillable.NUM_FILLTYPES;
64 desc.massPerLiter = Utils.getNoNil(massPerLiter, 0.0001);
65 desc.pricePerLiter = Utils.getNoNil(pricePerLiter, 0);
66 desc.previousHourPrice = desc.pricePerLiter;
67 desc.startPricePerLiter = desc.pricePerLiter;
68 desc.totalAmount = Fillable.FILLTYPE_START_TOTAL_AMOUNT;
69 desc.partOfEconomy = Utils.getNoNil(partOfEconomy, false);
70 desc.hudOverlayFilename = hudOverlayFilename;
71 desc.hudOverlayFilenameSmall = Utils.getNoNil(hudOverlayFilenameSmall, hudOverlayFilename);
72 desc.materials = {}
73 desc.maxPhysicalSurfaceAngle = maxPhysicalSurfaceAngle;
74
75 Fillable.fillTypeIndexToDesc[Fillable.NUM_FILLTYPES] = desc;
76 Fillable.fillTypeNameToDesc[name] = desc;
77
78 if desc.partOfEconomy then
79 table.insert(Fillable.economyFillTypes, desc);
80 end;
81 end;
82 return Fillable[key];
83end;
84
85function Fillable.onCreateFillMaterial(_, id)
86 local fillType = getUserAttribute(id, "fillType");
87 if fillType == nil then
88 print("Warning: No fillType '"..tostring(fillType).."' given for Fillable.onCreateMaterial");
89 return
90 end;
91
92 local desc = Fillable.fillTypeNameToDesc[fillType];
93 if desc == nil then
94 print("Warning: Unkown fillType '"..tostring(fillType).."' for Fillable.onCreateFillMaterial");
95 return;
96 end;
97
98 local matTypeName = getUserAttribute(id, "materialType");
99 if matTypeName == nil then
100 print("Warning: No materialtype given for filltype '"..tostring(fillType).."' for Fillable.onCreateFillMaterial");
101 return;
102 end;
103
104 local materialType = Fillable.getMaterialType(matTypeName);
105 if materialType == nil then
106 print("Warning: Unkown materialtype '"..matTypeName.."' given for filltype '"..tostring(fillType).."' for Fillable.onCreateFillMaterial");
107 return;
108 end;
109
110 local matIdStr = Utils.getNoNil(getUserAttribute(id, "materialId"), 1);
111 if tonumber(matIdStr) == nil then
112 print("Warning: Invalid materialId '"..matIdStr.."' for "..desc.name.."-"..matTypeName.."!")
113 return;
114 end;
115
116 local materialId = tonumber(matIdStr);
117
118 if desc.materials[materialType] == nil then
119 desc.materials[materialType] = {};
120 end;
121 local materials = desc.materials[materialType];
122 if Fillable.defaultMaterials[materialType] == nil then
123 Fillable.defaultMaterials[materialType] = {};
124 end;
125 local default = Fillable.defaultMaterials[materialType];
126
127 materials[materialId] = getMaterial(id, 0);
128 if default[materialId] == nil then
129 default[materialId] = materials[materialId];
130 end;
131end;
132
133function Fillable.getFillMaterial(fillType, materialType, materialTypeId)
134 if materialType == nil or materialTypeId == nil then
135 return nil;
136 end;
137
138 local desc = Fillable.fillTypeIndexToDesc[fillType];
139 if desc == nil then
140 return;
141 end;
142
143 local types = desc.materials[materialType];
144 local isDefault = false;
145
146 if types == nil then
147 types = Fillable.defaultMaterials[materialType];
148 isDefault = true;
149 end;
150 if types == nil then
151 return nil;
152 end;
153
154 if types[materialTypeId] ~= nil then
155 return types[materialTypeId], isDefault;
156 end;
157
158 return types[1], isDefault;
159end;
160
161function Fillable.getMaterialType(materialTypeName)
162 local key = "MATERIAL_TYPE_"..string.upper(materialTypeName);
163 return Fillable[key];
164end;
165
166function Fillable.cleanup()
167 for i=1, Fillable.NUM_FILLTYPES do
168 local desc = Fillable.fillTypeIndexToDesc[i];
169 if desc ~= nil then
170 desc.materials = {};
171 end;
172 end;
173 Fillable.defaultMaterials = {};
174end;
175
176function Fillable.addFillTypeToEconomy(index)
177 if not Fillable.fillTypeIndexToDesc[index].partOfEconomy then
178 Fillable.fillTypeIndexToDesc[index].partOfEconomy = true;
179 table.insert(Fillable.economyFillTypes, desc);
180 end
181end;
182
183function Fillable.prerequisitesPresent(specializations)
184 return true;
185end;
186
187function Fillable:load(xmlFile)
188
189 self.allowFillType = Fillable.allowFillType;
190 self.resetFillLevelIfNeeded = Fillable.resetFillLevelIfNeeded;
191 self.setFillLevel = Fillable.setFillLevel;
192 self.getFillLevel = Fillable.getFillLevel;
193 self.getCapacity = Fillable.getCapacity;
194 self.setCapacity = Fillable.setCapacity;
195 self.getAllowFillFromAir = Fillable.getAllowFillFromAir;
196 self.getFirstEnabledFillType = Fillable.getFirstEnabledFillType;
197 self.setLastValidFillType = SpecializationUtil.callSpecializationsFunction("setLastValidFillType");
198 self.getOverlayFillType = Fillable.getOverlayFillType;
199 self.getDoRenderFillType = Fillable.getDoRenderFillType;
200 self.updateMeasurementNode = Fillable.updateMeasurementNode;
201 self.attachPipe = Fillable.attachPipe;
202 self.detachPipe = Fillable.detachPipe;
203
204 self.supportsFillTriggers = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.supportsFillTriggers#value"), self.supportsFillTriggers);
205
206 if self.supportsFillTriggers then
207 assert(self.setIsFilling == nil, "Fillable needs to be the first specialization which implements setIsFilling");
208 self.setIsFilling = Fillable.setIsFilling;
209 self.addFillTrigger = Fillable.addFillTrigger;
210 self.removeFillTrigger = Fillable.removeFillTrigger;
211 self.fillLitersPerSecond = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.fillLitersPerSecond"), 500);
212 local unitFillTime = getXMLFloat(xmlFile, "vehicle.unitFillTime");
213 if unitFillTime ~= nil then
214 self.unitFillTime = unitFillTime * 1000;
215 end;
216 self.currentFillTime = 0;
217 self.fillTriggers = {};
218 self.fillActivatable = FillActivatable:new(self);
219 self.isFilling = false;
220 end;
221
222 self.fillLevel = 0;
223 self.capacity = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.capacity"), 0.0);
224 self.fillTypeChangeThreshold = 0.05; -- fill level percentage that still allows overriding with another fill type
225
226 self.synchronizeFillLevel = true;
227 self.synchronizeFullFillLevel = false;
228
229 self.fillRootNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.fillRootNode#index"));
230 if self.fillRootNode == nil then
231 self.fillRootNode = self.components[1].node;
232 end;
233
234 self.fillMassNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.fillMassNode#index"));
235 if self.fillMassNode == nil then
236 self.fillMassNode = self.fillRootNode;
237 end;
238
239 self.exactFillRootNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.exactFillRootNode#index"));
240 if self.exactFillRootNode == nil then
241 self.exactFillRootNode = self.fillRootNode;
242 end;
243
244 self.fillAutoAimTargetNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.fillAutoAimTargetNode#index"));
245 if self.fillAutoAimTargetNode == nil then
246 self.fillAutoAimTargetNode = self.exactFillRootNode;
247 end;
248
249 self.attacherPipeRef = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.attacherPipe#refIndex"));
250 self.attacherPipeRefVehicle = nil;
251
252 self.attacherPipe = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.attacherPipe#index"));
253 self.attacherPipeVehicle = nil;
254
255
256 self.fillTypes = {};
257 self.fillTypes[Fillable.FILLTYPE_UNKNOWN] = true;
258
259 local fillTypes = getXMLString(xmlFile, "vehicle.fillTypes#fillTypes");
260 if fillTypes ~= nil then
261 local types = Utils.splitString(" ", fillTypes);
262 for k,v in pairs(types) do
263 local fillType = Fillable.fillTypeNameToInt[v];
264 if fillType ~= nil then
265 self.fillTypes[fillType] = true;
266 else
267 print("Warning: '"..self.configFileName.. "' has invalid fillType '"..v.."'.");
268 end;
269 end;
270 end;
271 local fruitTypes = getXMLString(xmlFile, "vehicle.fillTypes#fruitTypes");
272 if fruitTypes ~= nil then
273 local types = Utils.splitString(" ", fruitTypes);
274 for k,v in pairs(types) do
275 local fillType = Fillable.fillTypeNameToInt[v];
276 if fillType ~= nil then
277 self.fillTypes[fillType] = true;
278 else
279 print("Warning: '"..self.configFileName.. "' has invalid fillType '"..v.."'.");
280 end;
281 end;
282 end;
283
284 self.currentFillType = Fillable.FILLTYPE_UNKNOWN;
285 self.lastValidFillType = Fillable.FILLTYPE_UNKNOWN;
286
287 if self.isServer then
288 self.sentFillType = self.currentFillType;
289 self.sentFillLevel = self.fillLevel;
290 end;
291
292 self.alsoUseFillVolumeLoadInfoForDischarge = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.alsoUseFillVolumeLoadInfoForDischarge"), false);
293
294 if self.isClient then
295 self.fillVolumes = {};
296 self.fillVolumeDeformers = {};
297 local i = 0;
298 while true do
299 local key = string.format("vehicle.fillVolumes.fillVolume(%d)", i);
300 if not hasXMLProperty(xmlFile, key) then
301 break;
302 end;
303
304 local fillVolume = {};
305
306 fillVolume.baseNode = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#index"));
307 fillVolume.allSidePlanes = Utils.getNoNil(getXMLBool(xmlFile, key.."#allSidePlanes"), true);
308
309 local defaultFillType = getXMLString(xmlFile, key.."#defaultFillType");
310 if defaultFillType ~= nil then
311
312 local fillType = Fillable.fillTypeNameToInt[defaultFillType];
313 if fillType ~= nil then
314 fillVolume.defaultFillType = fillType;
315 else
316 print("Warning: Invalid defaultFillType '"..tostring(defaultFillType).."' in '"..self.configFileName.."'");
317 end;
318 end;
319
320 fillVolume.maxDelta = Utils.getNoNil(getXMLFloat(xmlFile, key.."#maxDelta"), 1.0);
321 fillVolume.maxSurfaceAngle = math.rad( Utils.getNoNil(getXMLFloat(xmlFile, key.."#maxAllowedHeapAngle"), 35) );
322
323 local maxPhysicalSurfaceAngle = math.rad(35);
324 fillVolume.maxSubDivEdgeLength = Utils.getNoNil(getXMLFloat(xmlFile, key.."#maxSubDivEdgeLength"), 0.9);
325
326 fillVolume.volume = createFillPlaneShape(fillVolume.baseNode, "fillPlane", self.capacity, fillVolume.maxDelta, fillVolume.maxSurfaceAngle, maxPhysicalSurfaceAngle, fillVolume.maxSubDivEdgeLength, fillVolume.allSidePlanes);
327
328 fillVolume.deformers = {};
329 if fillVolume.volume ~= nil then
330 local j = 0;
331 while true do
332 local node = Utils.indexToObject(self.components, getXMLString(xmlFile, key..".deformNode("..j..")#index"));
333 if node == nil then
334 break;
335 end;
336 local initPos = { localToLocal(node, fillVolume.baseNode, 0,0,0) };
337 local polyline = findPolyline(fillVolume.volume, initPos[1],initPos[3]);
338 self.fillVolumeDeformers[node] = {node=node, initPos=initPos, posX=initPos[1], posZ=initPos[3], polyline=polyline, volume=fillVolume.volume, baseNode=fillVolume.baseNode};
339 j = j + 1;
340 end;
341 end;
342
343 fillVolume.scrollSpeedDischarge = { Utils.getVectorFromString(Utils.getNoNil(getXMLString(xmlFile, key.."#scrollSpeedDischarge"), "0 0 0")) };
344 fillVolume.scrollSpeedLoad = { Utils.getVectorFromString(Utils.getNoNil(getXMLString(xmlFile, key.."#scrollSpeedLoad"), "0 0 0")) };
345 for i=1,3 do
346 fillVolume.scrollSpeedDischarge[i] = fillVolume.scrollSpeedDischarge[i] / 1000;
347 fillVolume.scrollSpeedLoad[i] = fillVolume.scrollSpeedLoad[i] / 1000;
348 end;
349 fillVolume.uvPosition = {0, 0, 0};
350
351 if fillVolume.volume ~= nil and fillVolume.volume ~= 0 then
352 link(fillVolume.baseNode, fillVolume.volume);
353 table.insert(self.fillVolumes, fillVolume);
354 end;
355
356 i = i + 1;
357 end;
358
359
360 self.fillVolumeHeights = {};
361 self.fillVolumeHeightRefNodeToFillVolumeHeight = {};
362 local i=0;
363 while true do
364 local key = string.format("vehicle.fillVolumeHeights.fillVolumeHeight(%d)", i);
365 if not hasXMLProperty(xmlFile, key) then
366 break;
367 end;
368 local volumeHeight = {};
369 volumeHeight.fillVolumeId = getXMLInt(xmlFile, key.."#fillVolumeId");
370 volumeHeight.volumeHeightIsDirty = false;
371
372 volumeHeight.refNodes = {};
373 local j=0;
374 while true do
375 local refNode = Utils.indexToObject(self.components, getXMLString(xmlFile, string.format("%s.refNode(%d)#index", key, j)));
376 if refNode == nil then
377 break;
378 end;
379 table.insert(volumeHeight.refNodes, {refNode=refNode});
380 self.fillVolumeHeightRefNodeToFillVolumeHeight[refNode] = volumeHeight;
381 j=j+1;
382 end;
383
384 volumeHeight.nodes = {};
385 local j=0;
386 while true do
387 local node = Utils.indexToObject(self.components, getXMLString(xmlFile, string.format("%s.node(%d)#index", key, j)));
388 if node == nil then
389 break;
390 end;
391 if node ~= nil then
392 local baseScale = { Utils.getVectorFromString(Utils.getNoNil(getXMLString(xmlFile, string.format("%s.node(%d)#baseScale", key, j)), "1 1 1")) };
393 local scaleAxis = { Utils.getVectorFromString(Utils.getNoNil(getXMLString(xmlFile, string.format("%s.node(%d)#scaleAxis", key, j)), "0 0 0")) };
394 local scaleMax = { Utils.getVectorFromString(Utils.getNoNil(getXMLString(xmlFile, string.format("%s.node(%d)#scaleMax", key, j)), "0 0 0")) };
395 local basePosition = { getTranslation(node) };
396 local transAxis = { Utils.getVectorFromString(Utils.getNoNil(getXMLString(xmlFile, string.format("%s.node(%d)#transAxis", key, j)), "0 0 0")) };
397 local transMax = { Utils.getVectorFromString(Utils.getNoNil(getXMLString(xmlFile, string.format("%s.node(%d)#transMax", key, j)), "0 0 0")) };
398 local orientateToWorldY = Utils.getNoNil(getXMLBool(xmlFile, string.format("%s.node(%d)#orientateToWorldY", key, j)), false);
399 table.insert(volumeHeight.nodes, {node=node, baseScale=baseScale, scaleAxis=scaleAxis, scaleMax=scaleMax, basePosition=basePosition, transAxis=transAxis, transMax=transMax, orientateToWorldY=orientateToWorldY});
400 end;
401 j=j+1;
402 end;
403
404 table.insert(self.fillVolumeHeights, volumeHeight);
405 i=i+1;
406 end;
407
408 local fillPlanesRotDeg = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.fillPlanes#rotationDegrees"), false);
409 self.fillPlanes = {};
410 local i = 0;
411 while true do
412 local key = string.format("vehicle.fillPlanes.fillPlane(%d)", i);
413 if not hasXMLProperty(xmlFile, key) then
414 break;
415 end;
416 local fillPlane = {};
417 fillPlane.nodes = {};
418 local fillType = getXMLString(xmlFile, key.."#type");
419 if fillType ~= nil then
420 local nodeI = 0;
421 while true do
422 local nodeKey = key..string.format(".node(%d)", nodeI);
423 if not hasXMLProperty(xmlFile, nodeKey) then
424 break;
425 end;
426 local node = Utils.indexToObject(self.components, getXMLString(xmlFile, nodeKey.."#index"));
427 if node ~= nil then
428 local defaultX, defaultY, defaultZ = getTranslation(node);
429 local defaultRX, defaultRY, defaultRZ = getRotation(node);
430 setVisibility(node, false);
431
432 local animCurve = AnimCurve:new(linearInterpolatorTransRotScale);
433 local keyI = 0;
434 while true do
435 local animKey = nodeKey..string.format(".key(%d)", keyI);
436 local keyTime = getXMLFloat(xmlFile, animKey.."#time");
437 local x,y,z = Utils.getVectorFromString(getXMLString(xmlFile, animKey.."#translation"));
438 if y == nil then
439 y = getXMLFloat(xmlFile, animKey.."#y");
440 end;
441 local rx,ry,rz = Utils.getVectorFromString(getXMLString(xmlFile, animKey.."#rotation"));
442 local sx,sy,sz = Utils.getVectorFromString(getXMLString(xmlFile, animKey.."#scale"));
443 if keyTime == nil then
444 break;
445 end;
446 local x = Utils.getNoNil(x, defaultX);
447 local y = Utils.getNoNil(y, defaultY);
448 local z = Utils.getNoNil(z, defaultZ);
449 if fillPlanesRotDeg then
450 rx = Utils.getNoNilRad(rx, defaultRX);
451 ry = Utils.getNoNilRad(ry, defaultRY);
452 rz = Utils.getNoNilRad(rz, defaultRZ);
453 else
454 rx = Utils.getNoNil(rx, defaultRX);
455 ry = Utils.getNoNil(ry, defaultRY);
456 rz = Utils.getNoNil(rz, defaultRZ);
457 end
458 local sx = Utils.getNoNil(sx, 1);
459 local sy = Utils.getNoNil(sy, 1);
460 local sz = Utils.getNoNil(sz, 1);
461 animCurve:addKeyframe({x=x, y=y, z=z, rx=rx, ry=ry, rz=rz, sx=sx, sy=sy, sz=sz, time = keyTime});
462 keyI = keyI +1;
463 end;
464 if keyI == 0 then
465 local minY, maxY = Utils.getVectorFromString(getXMLString(xmlFile, nodeKey.."#minMaxY"));
466 local minY = Utils.getNoNil(minY, defaultY);
467 local maxY = Utils.getNoNil(maxY, defaultY);
468 animCurve:addKeyframe({x=defaultX, y=minY, z=defaultZ, rx=defaultRX, ry=defaultRY, rz=defaultRZ, sx=1, sy=1, sz=1, time = 0});
469 animCurve:addKeyframe({x=defaultX, y=maxY, z=defaultZ, rx=defaultRX, ry=defaultRY, rz=defaultRZ, sx=1, sy=1, sz=1, time = 1});
470 end;
471 local alwaysVisible = Utils.getNoNil(getXMLBool(xmlFile, nodeKey.."#alwaysVisible"), false);
472 table.insert(fillPlane.nodes, {node=node, animCurve = animCurve, alwaysVisible=alwaysVisible});
473 end;
474 nodeI = nodeI +1;
475 end;
476 if table.getn(fillPlane.nodes) > 0 then
477 if self.defaultFillPlane == nil then
478 self.defaultFillPlane = fillPlane;
479 end;
480 self.fillPlanes[fillType] = fillPlane;
481 end;
482 end;
483 i = i +1;
484 end;
485 if self.defaultFillPlane==nil then
486 self.fillPlanes = nil;
487 end;
488
489 if self.fillPlanes == nil then
490 Fillable.loadDeprecatedTrailerGrainPlane(self, xmlFile);
491 --[[if hasXMLProperty(xmlFile, "vehicle.grainPlane") then
492 print("Warning: '"..self.configFileName.. "' uses old grainPlane format, which is not supported anymore.");
493 end;]]
494 end;
495
496 self.measurementNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.measurementNode#index"));
497 self.measurementTime = 0;
498 end;
499
500 self.allowFillFromAir = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.allowFillFromAir#value"), true);
501
502 local unloadTriggerNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.unloadTrigger#index"));
503 if unloadTriggerNode ~= nil then
504 self.unloadTrigger = FillTrigger:new();
505 self.unloadTrigger:load(unloadTriggerNode, self.currentFillType, self);
506 end;
507
508 if self.isServer then
509 local shovelFillTriggerId = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.shovelFillTrigger#index"));
510 if shovelFillTriggerId ~= nil then
511 local shovelFillTrigger = FillableShovelFillTrigger:new();
512 if shovelFillTrigger:load(shovelFillTriggerId, self) then
513 self.shovelFillTrigger = shovelFillTrigger;
514 else
515 shovelFillTrigger:delete();
516 end
517 end
518 end;
519
520
521 self.fillVolumeLoadInfo = {};
522 self.fillVolumeLoadInfo.name = "fillVolumeLoadInfo";
523
524 self.fillVolumeUnloadInfo = {};
525 self.fillVolumeUnloadInfo.name = "fillVolumeUnloadInfo";
526
527 self.fillVolumeDischargeInfo = {};
528 self.fillVolumeDischargeInfo.name = "fillVolumeDischargeInfo";
529
530 for _,tbl in pairs( {self.fillVolumeLoadInfo, self.fillVolumeUnloadInfo, self.fillVolumeDischargeInfo} ) do
531 local indexString = getXMLString(xmlFile, "vehicle."..tbl.name.."#index");
532 if indexString == nil then
533 tbl.node = createTransformGroup(tbl.name);
534 link(self.components[1].node, tbl.node);
535 setTranslation(tbl.node, 0,0,0);
536 else
537 tbl.node = Utils.indexToObject(self.components, indexString);
538 end;
539 tbl.width = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle."..tbl.name.."#width"), 1.0);
540 tbl.length = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle."..tbl.name.."#length"), 1.0);
541
542 if tbl.name == "fillVolumeDischargeInfo" then
543 tbl.alsoUseLoadInfoForDischarge = Utils.getNoNil(getXMLBool(xmlFile, "vehicle."..tbl.name.."#alsoUseLoadInfoForDischarge"), false);
544 tbl.loadInfoSizeScale = Utils.getVectorNFromString( Utils.getNoNil(getXMLString(xmlFile, "vehicle."..tbl.name.."#loadInfoSizeScale"), "1 1"), 2 );
545 tbl.loadInfoFillFactor = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle."..tbl.name.."#loadInfoFillFactor"), 0.6);
546 end;
547 end;
548
549
550 self:setFillLevel(0, Fillable.FILLTYPE_UNKNOWN);
551
552 setUserAttribute(self.fillRootNode, "vehicleType", "Integer", 2);
553
554 self.fillableDirtyFlag = self:getNextDirtyFlag();
555end;
556
557function Fillable:postLoad(xmlFile)
558 local startFillLevel = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.startFillLevel"), 0);
559 if startFillLevel > 0 then
560 local firstFillType = self:getFirstEnabledFillType();
561
562 if firstFillType ~= Fillable.FILLTYPE_UNKNOWN then
563 self:setFillLevel(startFillLevel, firstFillType, true);
564 end;
565 end;
566end;
567
568function Fillable.loadDeprecatedTrailerGrainPlane(self, xmlFile)
569
570 --self.grainPlane = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.grainPlane#index"));
571 if self.isClient then
572 if self.fillPlanes == nil then
573 local defaultX, defaultY, defaultZ;
574 local defaultRX, defaultRY, defaultRZ;
575 local defaultSX, defaultSY, defaultSZ;
576
577 self.fillPlanes = {};
578 local i = 0;
579 while true do
580 local key = string.format("vehicle.grainPlane.node(%d)", i);
581 local fruitType = getXMLString(xmlFile, key.."#type");
582 local index = getXMLString(xmlFile, key.."#index");
583 if fruitType==nil or index==nil then
584 break;
585 end;
586 local node = Utils.indexToObject(self.components, index);
587 if node ~= nil then
588 defaultX, defaultY, defaultZ = getTranslation(node);
589 defaultRX, defaultRY, defaultRZ = getRotation(node);
590 defaultSX, defaultSY, defaultSZ = getScale(node);
591
592 setVisibility(node, false);
593 local fillPlane = {};
594 fillPlane.nodes = {};
595 table.insert(fillPlane.nodes, {node=node, alwaysVisible=false}); -- animCurve is filled below
596 -- Node: fruitType names are equal to the fillType names
597 self.fillPlanes[fruitType] = fillPlane;
598
599 if self.defaultFillPlane == nil then
600 self.defaultFillPlane = fillPlane;
601 end;
602 end;
603 i = i +1;
604 end;
605 if self.defaultFillPlane==nil then
606 self.fillPlanes = nil;
607 else
608 local animCurve = AnimCurve:new(linearInterpolatorTransRotScale);
609 local keyI = 0;
610 while true do
611 local animKey = string.format("vehicle.grainPlane.key(%d)", keyI);
612 local keyTime = getXMLFloat(xmlFile, animKey.."#time");
613 local y = getXMLFloat(xmlFile, animKey.."#y");
614 local sx,sy,sz = Utils.getVectorFromString(getXMLString(xmlFile, animKey.."#scale"));
615 if keyTime == nil then
616 break;
617 end;
618 local x = Utils.getNoNil(x, defaultX);
619 local y = Utils.getNoNil(y, defaultY);
620 local z = Utils.getNoNil(z, defaultZ);
621 local rx = Utils.getNoNil(rx, defaultRX);
622 local ry = Utils.getNoNil(ry, defaultRY);
623 local rz = Utils.getNoNil(rz, defaultRZ);
624 local sx = Utils.getNoNil(sx, defaultSX);
625 local sy = Utils.getNoNil(sy, defaultSY);
626 local sz = Utils.getNoNil(sz, defaultSZ);
627 animCurve:addKeyframe({x=x, y=y, z=z, rx=rx, ry=ry, rz=rz, sx=sx, sy=sy, sz=sz, time = keyTime});
628 keyI = keyI +1;
629 end;
630 if keyI == 0 then
631 local minY, maxY = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.grainPlane#minMaxY"));
632 local minY = Utils.getNoNil(minY, defaultY);
633 local maxY = Utils.getNoNil(maxY, defaultY);
634 animCurve:addKeyframe({x=defaultX, y=minY, z=defaultZ, rx=defaultRX, ry=defaultRY, rz=defaultRZ, sx=defaultSX, sy=defaultSY, sz=defaultSZ, time = 0});
635 animCurve:addKeyframe({x=defaultX, y=maxY, z=defaultZ, rx=defaultRX, ry=defaultRY, rz=defaultRZ, sx=defaultSX, sy=defaultSY, sz=defaultSZ, time = 1});
636 end;
637
638 for _, fillPlane in pairs(self.fillPlanes) do
639 fillPlane.nodes[1].animCurve = animCurve;
640 end;
641 end;
642 end;
643 end;
644
645end;
646
647function Fillable:delete()
648 if self.unloadTrigger ~= nil then
649 self.unloadTrigger:delete();
650 self.unloadTrigger = nil;
651 end;
652
653 for _, fillVolume in pairs(self.fillVolumes) do
654 if fillVolume.volume ~= nil then
655 delete(fillVolume.volume);
656 end;
657 fillVolume.volume = nil;
658 end;
659
660 if self.fillActivatable ~= nil then
661 g_currentMission:removeActivatableObject(self.fillActivatable);
662 end;
663 if self.shovelFillTrigger ~= nil then
664 self.shovelFillTrigger:delete();
665 end
666end;
667
668function Fillable:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
669 if self.synchronizeFillLevel then
670 local fillLevel = getXMLFloat(xmlFile, key.."#fillLevel");
671 local fillType = getXMLString(xmlFile, key.."#fillType");
672 if fillLevel ~= nil and fillType ~= nil then
673 local fillTypeInt = Fillable.fillTypeNameToInt[fillType];
674 if fillTypeInt ~= nil then
675 local fillSourceStruct = {x=0,y=0,z=0, d1x=0,d1y=0,d1z=0, d2x=0,d2y=0,d2z=0};
676 self:setFillLevel(fillLevel, fillTypeInt, false, fillSourceStruct);
677 end;
678 end;
679 end
680 return BaseMission.VEHICLE_LOAD_OK;
681end;
682
683function Fillable:getSaveAttributesAndNodes(nodeIdent)
684 if self.synchronizeFillLevel then
685 local fillType = Fillable.fillTypeIntToName[self.currentFillType];
686 if fillType == nil then
687 fillType = "unknown";
688 end;
689 local attributes = 'fillLevel="'..self.fillLevel..'" fillType="'..fillType..'"';
690 return attributes, nil;
691 end
692 return nil;
693end;
694
695function Fillable:getXMLStatsAttributes()
696 local fillType = Fillable.fillTypeIntToName[self.currentFillType];
697 if fillType == nil then
698 fillType = "unknown";
699 end
700 return string.format('fillLevel="%.3f" fillType="%s"', self:getFillLevel(self.currentFillType), Utils.encodeToHTML(tostring(fillType)));
701end
702
703function Fillable:addNodeVehicleMapping(list)
704 list[self.fillRootNode] = self;
705 list[self.exactFillRootNode] = self;
706end;
707
708function Fillable:removeNodeVehicleMapping(list)
709 list[self.fillRootNode] = nil;
710 list[self.exactFillRootNode] = nil;
711end;
712
713function Fillable:mouseEvent(posX, posY, isDown, isUp, button)
714end;
715
716function Fillable:keyEvent(unicode, sym, modifier, isDown)
717end;
718
719function Fillable:readStream(streamId, connection)
720 if connection:getIsServer() then
721 if self.synchronizeFillLevel then
722 local fillLevel = streamReadFloat32(streamId);
723 local fillType = streamReadUIntN(streamId, Fillable.sendNumBits);
724 local fillSourceStruct = {x=0,y=0,z=0, d1x=0,d1y=0,d1z=0, d2x=0,d2y=0,d2z=0};
725 self:setFillLevel(fillLevel, fillType, false, fillSourceStruct);
726
727 local lastValidFillType = streamReadUIntN(streamId, Fillable.sendNumBits);
728 self:setLastValidFillType(lastValidFillType, true);
729 end
730 end
731 if self.supportsFillTriggers then
732 local isFilling = streamReadBool(streamId);
733 self:setIsFilling(isFilling, true);
734 end;
735end;
736
737function Fillable:writeStream(streamId, connection)
738 if not connection:getIsServer() then
739 if self.synchronizeFillLevel then
740 streamWriteFloat32(streamId, self.fillLevel);
741 streamWriteUIntN(streamId, self.currentFillType, Fillable.sendNumBits);
742 streamWriteUIntN(streamId, self.lastValidFillType, Fillable.sendNumBits);
743 end
744 end;
745 if self.supportsFillTriggers then
746 streamWriteBool(streamId, self.isFilling);
747 end;
748end;
749
750function Fillable:readUpdateStream(streamId, timestamp, connection)
751 if connection:getIsServer() then
752 if self.synchronizeFillLevel then
753 if streamReadBool(streamId) then
754 local fillLevel;
755 if self.synchronizeFullFillLevel then
756 fillLevel = streamReadFloat32(streamId);
757 else
758 fillLevel = streamReadUInt16(streamId)/65535*self:getCapacity();
759 end
760 local fillType = streamReadUIntN(streamId, Fillable.sendNumBits);
761
762 self:setFillLevel(fillLevel, fillType, true);
763 local lastValidFillType = streamReadUIntN(streamId, Fillable.sendNumBits);
764 self:setLastValidFillType(lastValidFillType, lastValidFillType ~= self.lastValidFillType); -- or self.currentFillType == Fillable.FILLTYPE_UNKNOWN
765 end;
766 end
767 end;
768end;
769
770function Fillable:writeUpdateStream(streamId, connection, dirtyMask)
771 if not connection:getIsServer() then
772 if self.synchronizeFillLevel then
773 if streamWriteBool(streamId, bitAND(dirtyMask, self.fillableDirtyFlag) ~= 0) then
774 if self.synchronizeFullFillLevel then
775 streamWriteFloat32(streamId, self.fillLevel);
776 else
777 local percent = 0;
778 if self:getCapacity() ~= 0 then
779 percent = Utils.clamp(self.fillLevel / self:getCapacity(), 0, 1);
780 end;
781 streamWriteUInt16(streamId, math.floor(percent*65535));
782 end
783 streamWriteUIntN(streamId, self.currentFillType, Fillable.sendNumBits);
784 streamWriteUIntN(streamId, self.lastValidFillType, Fillable.sendNumBits);
785 end;
786 end
787 end;
788end;
789
790function Fillable:update(dt)
791 if self.firstTimeRun then
792 if self.isServer then
793 if self.emptyMass == nil then
794 self.emptyMass = getMass(self.fillMassNode);
795 self.currentMass = self.emptyMass;
796 end;
797 local massScale = 0;
798 if self.currentFillType ~= nil and self.currentFillType ~= Fillable.FILLTYPE_UNKNOWN then
799 massScale = Fillable.fillTypeIndexToDesc[self.currentFillType].massPerLiter;
800 end;
801 local newMass = self.emptyMass + self.fillLevel*massScale;
802 if newMass ~= self.currentMass then
803 setMass(self.fillMassNode, newMass);
804 self.currentMass = newMass;
805 end;
806 end;
807 end;
808 if self.isClient and (self:getIsActive() or self.tipState == Trailer.TIPSTATE_OPENING or self.tipState == Trailer.TIPSTATE_OPEN) then
809 for _,deformer in pairs(self.fillVolumeDeformers) do
810 if deformer.deformerIsDirty and deformer.polyline ~= nil and deformer.polyline ~= -1 then
811 deformer.deformerIsDirty = false;
812 local posX, _, posZ = localToLocal(deformer.node, deformer.baseNode, 0,0,0);
813 local dirty = false;
814 if math.abs(posX - deformer.posX) > 0.0001 or math.abs(posZ - deformer.posZ) > 0.0001 then
815 deformer.lastPosX = posX;
816 deformer.lastPosZ = posZ;
817 local dx = posX - deformer.initPos[1];
818 local dz = posZ - deformer.initPos[3];
819 setPolylineTranslation(deformer.volume, deformer.polyline, dx,dz);
820 end;
821 end;
822 end;
823
824 for _,fillVolumeHeight in pairs(self.fillVolumeHeights) do
825 if fillVolumeHeight.volumeHeightIsDirty == true and self.fillVolumes[fillVolumeHeight.fillVolumeId] ~= nil then
826 fillVolumeHeight.volumeHeightIsDirty = false;
827
828 local baseNode = self.fillVolumes[fillVolumeHeight.fillVolumeId].baseNode;
829 local volumeNode = self.fillVolumes[fillVolumeHeight.fillVolumeId].volume;
830
831 if baseNode ~= nil and volumeNode ~= nil then
832
833 local minHeight = math.huge;
834 for _,refNode in pairs(fillVolumeHeight.refNodes) do
835 local x,_,z = localToLocal(refNode.refNode, baseNode, 0,0,0);
836 minHeight = math.min(minHeight, getFillPlaneHeightAtLocalPos(volumeNode, x,z));
837 end;
838
839 for _,node in pairs(fillVolumeHeight.nodes) do
840 local sx = node.scaleAxis[1]*minHeight;
841 local sy = node.scaleAxis[2]*minHeight;
842 local sz = node.scaleAxis[3]*minHeight;
843 if node.scaleMax[1] > 0 then
844 sx = math.min(node.scaleMax[1], sx);
845 end
846 if node.scaleMax[2] > 0 then
847 sy = math.min(node.scaleMax[2], sy);
848 end
849 if node.scaleMax[3] > 0 then
850 sz = math.min(node.scaleMax[3], sz);
851 end
852 local tx = node.transAxis[1]*minHeight;
853 local ty = node.transAxis[2]*minHeight;
854 local tz = node.transAxis[3]*minHeight;
855 if node.transMax[1] > 0 then
856 tx = math.min(node.transMax[1], tx);
857 end
858 if node.transMax[2] > 0 then
859 ty = math.min(node.transMax[2], ty);
860 end
861 if node.transMax[3] > 0 then
862 tz = math.min(node.transMax[3], tz);
863 end
864
865 setScale(node.node, node.baseScale[1]+sx, node.baseScale[2]+sy, node.baseScale[3]+sz);
866 setTranslation(node.node, node.basePosition[1]+tx, node.basePosition[2]+ty, node.basePosition[3]+tz);
867
868 if node.orientateToWorldY then
869 local dx,dy,dz = localDirectionToWorld(getParent(node.node), 0,1,0);
870 local alpha = math.acos(dy);
871 setRotation(node.node, alpha,0,0);
872 end;
873 end;
874 end;
875 end;
876 end;
877 end;
878end;
879
880function Fillable:setMovingToolDirty(node)
881 if self.fillVolumeDeformers[node] ~= nil then
882 self.fillVolumeDeformers[node].deformerIsDirty = true;
883 end;
884 if self.fillVolumeHeightRefNodeToFillVolumeHeight[node] ~= nil then
885 self.fillVolumeHeightRefNodeToFillVolumeHeight[node].volumeHeightIsDirty = true;
886 end;
887end
888
889function Fillable:updateTick(dt)
890 if self.isServer then
891 if self.synchronizeFillLevel then
892 if self.fillLevel ~= self.sentFillLevel or self.currentFillType ~= self.sentFillType or self.lastValidFillType ~= self.sentLastValidFillType then
893 self:raiseDirtyFlags(self.fillableDirtyFlag);
894 self.sentLastValidFillType = self.lastValidFillType;
895 self.sentFillLevel = self.fillLevel;
896 self.sentFillType = self.currentFillType;
897 end;
898 end
899 if self.shovelFillTrigger ~= nil then
900 self.shovelFillTrigger:update(dt);
901 end
902
903 if self.isFilling then
904 local delta = 0;
905 local doFill = false;
906 if self.fillTrigger ~= nil then
907 if self.unitFillTime ~= nil then
908 self.currentFillTime = self.currentFillTime - dt;
909 if self.currentFillTime <= 0 then
910 doFill = true;
911 delta = self.fillTrigger:fill(self, 1);
912 self.currentFillTime = self.unitFillTime;
913 end;
914 else
915 delta = self.fillLitersPerSecond*dt*0.001;
916 delta = self.fillTrigger:fill(self, delta);
917 doFill = true;
918 end;
919 end
920
921 if delta <= 0 and doFill then
922 self:setIsFilling(false);
923 end;
924 end
925 end;
926
927 if self.isClient then
928 if self.measurementTime > 0 then
929 self.measurementTime = self.measurementTime - dt;
930 if self.measurementTime <= 0 then
931 self:updateMeasurementNode();
932 end;
933 end;
934 end;
935end;
936
937function Fillable:draw()
938 if self.isClient then
939 if self:getDoRenderFillType() then
940 local fillType = self:getOverlayFillType()
941 if fillType ~= Fillable.FILLTYPE_UNKNOWN then
942 g_currentMission:setFillTypeOverlayFillType(fillType);
943 end;
944 end;
945 end;
946end;
947
948function Fillable:getAdditiveClientMass()
949 local massScale = 0;
950 if self.currentFillType ~= nil and self.currentFillType ~= Fillable.FILLTYPE_UNKNOWN then
951 massScale = Fillable.fillTypeIndexToDesc[self.currentFillType].massPerLiter;
952 end;
953 return self.fillLevel*massScale;
954end;
955
956function Fillable:resetFillLevelIfNeeded(fillType)
957 if self.currentFillType ~= fillType then
958 self.fillLevel = 0;
959 end;
960end;
961
962function Fillable:allowFillType(fillType, allowEmptying)
963 local allowed = false;
964
965 if self.fillTypes[fillType] then
966 if self.currentFillType ~= Fillable.FILLTYPE_UNKNOWN then
967 if self.currentFillType ~= fillType then
968 if self.fillLevel <= self:getCapacity()*self.fillTypeChangeThreshold then
969 allowed = true; -- fill level is low enough to be overridden
970 if allowEmptying then
971 self.fillLevel = 0; -- empty the trailer
972 end;
973 end;
974 else
975 allowed = true; -- fill type is the same as the trailer's current fill type
976 end;
977 else
978 allowed = true; -- fillable is empty --> Fillable.FILLTYPE_UNKNOWN
979 end;
980 end;
981
982 return allowed;
983end;
984
985function Fillable:getFillLevel(fillType)
986 if fillType == self.currentFillType then
987 return self.fillLevel;
988 end
989 return 0;
990end
991
992function Fillable:setFillLevel(fillLevel, fillType, force, fillSourceStruct)
993 if (force == nil or force == false) and not self:allowFillType(fillType, false) then
994 return
995 end;
996
997 if fillType ~= self.currentFillType then
998 local maxPhysicalSurfaceAngle;
999 if FruitUtil.fruitIndexToDesc[fillType] ~= nil then
1000 maxPhysicalSurfaceAngle = FruitUtil.fruitIndexToDesc[fillType].maxPhysicalSurfaceAngle;
1001 elseif Fillable.fillTypeIntToName[fillType] ~= nil then
1002 maxPhysicalSurfaceAngle = Fillable.fillTypeIntToName[fillType].maxPhysicalSurfaceAngle;
1003 end;
1004 if maxPhysicalSurfaceAngle ~= nil then
1005 for _,fillVolume in pairs(self.fillVolumes) do
1006 if fillVolume.volume ~= nil then
1007 setFillPlaneMaxPhysicalSurfaceAngle(fillVolume.volume, maxPhysicalSurfaceAngle);
1008 end;
1009 end;
1010 end;
1011 end;
1012
1013 if fillLevel < self.fillLevel and fillLevel < 0.0000001 then
1014 fillLevel = 0;
1015 end;
1016
1017 local delta = math.min(fillLevel-self.fillLevel, self.capacity);
1018 local lastFillType = self.currentFillType;
1019 self.currentFillType = fillType;
1020 self.fillLevel = fillLevel;
1021
1022 if self:getCapacity() == 0 then
1023 self.fillLevel = math.max(fillLevel, 0);
1024 else
1025 self.fillLevel = Utils.clamp(fillLevel, 0, self:getCapacity());
1026 end;
1027
1028 if self.fillLevel <= 0 then
1029 self.fillLevel = 0;
1030 self.currentFillType = Fillable.FILLTYPE_UNKNOWN;
1031 end;
1032
1033 if self.unloadTrigger ~= nil then
1034 self.unloadTrigger.fillType = self.currentFillType;
1035 end;
1036
1037 if self.isClient then
1038 if self.currentFillPlane ~= nil then
1039 for _, node in ipairs(self.currentFillPlane.nodes) do
1040 setVisibility(node.node, false);
1041 end;
1042 self.currentFillPlane = nil;
1043 end;
1044 if self.fillPlanes ~= nil and self.defaultFillPlane ~= nil then
1045 local fillPlane;
1046 local t = 0;
1047 if fillType ~= Fillable.FILLTYPE_UNKNOWN then
1048 local fillTypeName = Fillable.fillTypeIntToName[fillType];
1049 fillPlane = self.fillPlanes[fillTypeName];
1050 t = self.fillLevel/self:getCapacity();
1051 end
1052 if fillPlane == nil then
1053 fillPlane = self.defaultFillPlane
1054 end
1055 for _, node in ipairs(fillPlane.nodes) do
1056 local x,y,z, rx,ry,rz, sx,sy,sz = node.animCurve:get(t);
1057
1058 setTranslation(node.node, x, y, z);
1059 setRotation(node.node, rx, ry, rz);
1060 setScale(node.node, sx, sy, sz);
1061 setVisibility(node.node, self.fillLevel > 0 or node.alwaysVisible);
1062 end;
1063 self.currentFillPlane = fillPlane;
1064 end;
1065
1066 local materialId = nil;
1067 local isDefault = false;
1068 if self.currentFillType ~= Fillable.FILLTYPE_UNKNOWN and self.currentFillType ~= lastFillType then
1069 local usedFillType = self.currentFillType;
1070 if self.forcedFillPlaneType ~= nil then
1071 usedFillType = self.forcedFillPlaneType;
1072 end;
1073 materialId, isDefault = Fillable.getFillMaterial(usedFillType, Fillable.MATERIAL_TYPE_FILLPLANE, 1);
1074 end;
1075
1076 for _, fillVolume in pairs(self.fillVolumes) do
1077
1078 setVisibility(fillVolume.volume, self.fillLevel > 0);
1079
1080 if self.currentFillType ~= Fillable.FILLTYPE_UNKNOWN and self.currentFillType ~= lastFillType then
1081 if isDefault and fillVolume.defaultFillType ~= nil then
1082 materialId = Fillable.getFillMaterial(fillVolume.defaultFillType, Fillable.MATERIAL_TYPE_FILLPLANE, 1);
1083 end;
1084 if materialId ~= nil then
1085 setMaterial(fillVolume.volume, materialId, 0);
1086 end;
1087 end;
1088
1089 if fillSourceStruct ~= nil then
1090 local fss = fillSourceStruct;
1091 if Vehicle.debugRendering then
1092 drawDebugLine( fss.x, fss.y, fss.z, 1,0,0, fss.x+fss.d1x, fss.y+fss.d1y, fss.z+fss.d1z, 1,0,0 );
1093 drawDebugLine( fss.x, fss.y, fss.z, 0,0,1, fss.x+fss.d2x, fss.y+fss.d2y, fss.z+fss.d2z, 0,0,1 );
1094 drawDebugPoint( fss.x, fss.y, fss.z, 1,1,1,1 );
1095 drawDebugPoint( fss.x+fss.d1x, fss.y+fss.d1y, fss.z+fss.d1z, 1,0,0,1 );
1096 drawDebugPoint( fss.x+fss.d2x, fss.y+fss.d2y, fss.z+fss.d2z, 0,0,1,1 );
1097 end;
1098 fss.x = fss.x - (fss.d1x + fss.d2x) / 2;
1099 fss.y = fss.y - (fss.d1y + fss.d2y) / 2;
1100 fss.z = fss.z - (fss.d1z + fss.d2z) / 2;
1101 fillPlaneAdd(fillVolume.volume, delta, fss.x,fss.y,fss.z, fss.d1x,fss.d1y,fss.d1z, fss.d2x,fss.d2y,fss.d2z);
1102 else
1103 local x,y,z = localToWorld(fillVolume.volume, 0,100,0);
1104 local d1x,d1y,d1z = localDirectionToWorld(fillVolume.volume, 5,0,0);
1105 local d2x,d2y,d2z = localDirectionToWorld(fillVolume.volume, 0,0,5);
1106 x = x - (d1x+d2x)/2;
1107 y = y - (d1y+d2y)/2;
1108 z = z - (d1z+d2z)/2;
1109 fillPlaneAdd(fillVolume.volume, delta, x,y,z, d1x,d1y,d1z, d2x,d2y,d2z);
1110 end;
1111 end;
1112 end;
1113
1114 if self.currentFillType ~= Fillable.FILLTYPE_UNKNOWN then
1115 self:setLastValidFillType(fillType, self.lastValidFillType ~= self.currentFillType);
1116 end
1117
1118 self.measurementTime = 5000;
1119 self:updateMeasurementNode();
1120end;
1121
1122function Fillable:setCapacity(capacity)
1123 self.capacity = capacity;
1124end;
1125
1126function Fillable:getCapacity()
1127 return self.capacity;
1128end;
1129
1130function Fillable:getAllowFillFromAir()
1131 return self.allowFillFromAir;
1132end;
1133
1134function Fillable:getFirstEnabledFillType()
1135 for fillType, enabled in pairs(self.fillTypes) do
1136 if fillType ~= Fillable.FILLTYPE_UNKNOWN and enabled then
1137 return fillType;
1138 end
1139 end
1140 return Fillable.FILLTYPE_UNKNOWN;
1141end
1142
1143function Fillable:setLastValidFillType(lastValidFillType, hasChanged)
1144 if self.lastValidFillType ~= lastValidFillType then
1145 self.lastValidFillType = lastValidFillType;
1146 end;
1147end;
1148
1149function Fillable:getOverlayFillType()
1150 if self.currentFillType ~= Fillable.FILLTYPE_UNKNOWN then
1151 return self.currentFillType;
1152 end;
1153 return Fillable.FILLTYPE_UNKNOWN;
1154end;
1155
1156function Fillable:getDoRenderFillType()
1157 return self.currentFillType ~= Fillable.FILLTYPE_UNKNOWN;
1158end;
1159
1160function Fillable:setIsFilling(isFilling, noEventSend)
1161 SetIsFillingEvent.sendEvent(self, isFilling, noEventSend)
1162 if self.isFilling ~= isFilling then
1163 self.isFilling = isFilling;
1164
1165 self.fillTrigger = nil;
1166 if isFilling then
1167 -- find the first trigger which is activable
1168 for i, trigger in ipairs(self.fillTriggers) do
1169 if trigger:getIsActivatable(self) then
1170 self.fillTrigger = trigger;
1171 break;
1172 end;
1173 end;
1174 end
1175 end;
1176end;
1177
1178function Fillable:addFillTrigger(trigger)
1179 if table.getn(self.fillTriggers) == 0 then
1180 g_currentMission:addActivatableObject(self.fillActivatable);
1181 end;
1182 table.insert(self.fillTriggers, trigger);
1183end;
1184
1185function Fillable:removeFillTrigger(trigger)
1186 for i=1, table.getn(self.fillTriggers) do
1187 if self.fillTriggers[i] == trigger then
1188 table.remove(self.fillTriggers, i);
1189 break;
1190 end;
1191 end;
1192 if table.getn(self.fillTriggers) == 0 then
1193 if self.isServer then
1194 self:setIsFilling(false);
1195 end;
1196 g_currentMission:removeActivatableObject(self.fillActivatable);
1197 end;
1198end;
1199
1200function Fillable:updateMeasurementNode()
1201 if self.measurementNode ~= nil then
1202 local isWorking = 1;
1203 if self.measurementTime <= 0 then
1204 isWorking = 0;
1205 end;
1206 setShaderParameter(self.measurementNode, "fillLevel", self.fillLevel/self:getCapacity(), isWorking, 0, 0, false);
1207 end;
1208end;
1209
1210function Fillable:onAttach(attacherVehicle)
1211 if self.attacherPipe ~= nil then
1212 local vehicle = Fillable.findAttacherPipeVehicle(self:getRootAttacherVehicle(), true);
1213 if vehicle ~= nil then
1214 self:attachPipe(self, vehicle);
1215 end;
1216 elseif self.attacherPipeRef ~= nil then
1217 local vehicle = Fillable.findAttacherPipeVehicle(self:getRootAttacherVehicle(), false);
1218 if vehicle ~= nil then
1219 self:attachPipe(vehicle, self);
1220 end;
1221 end;
1222end;
1223
1224function Fillable:onDetach()
1225 self:detachPipe();
1226end;
1227
1228function Fillable:attachPipe(pipeVehicle, refVehicle)
1229 pipeVehicle.attacherPipeRefVehicle = refVehicle;
1230 refVehicle.attacherPipeVehicle = pipeVehicle;
1231
1232 for _, movingPart in pairs(pipeVehicle.activeDirtyMovingParts) do
1233 if movingPart.node == pipeVehicle.attacherPipe then
1234 movingPart.referenceFrame = refVehicle.attacherPipeRef;
1235 movingPart.referenceFrameOffset = {0,0,0};
1236 Cylindered.updateMovingPart(self, movingPart, false);
1237 break;
1238 end;
1239 end;
1240end;
1241
1242function Fillable:detachPipe()
1243 if self.attacherPipeRefVehicle ~= nil then
1244 for _, movingPart in pairs(self.activeDirtyMovingParts) do
1245 if movingPart.node == self.attacherPipe then
1246 movingPart.referenceFrame = self.rootNode;
1247 break;
1248 end;
1249 end;
1250 self.attacherPipeRefVehicle.attacherPipeVehicle = nil;
1251 self.attacherPipeRefVehicle = nil;
1252 end;
1253 if self.attacherPipeVehicle ~= nil then
1254 for _, movingPart in pairs(self.attacherPipeVehicle.activeDirtyMovingParts) do
1255 if movingPart.node == self.attacherPipeVehicle.attacherPipe then
1256 movingPart.referenceFrame = self.attacherPipeVehicle.rootNode;
1257 break;
1258 end;
1259 end;
1260 self.attacherPipeVehicle.attacherPipeRefVehicle = nil;
1261 local attacherPipeVehicle = self.attacherPipeVehicle;
1262 self.attacherPipeVehicle = nil;
1263 -- try to reattach
1264 local vehicle = Fillable.findAttacherPipeVehicle(attacherPipeVehicle:getRootAttacherVehicle(), true);
1265 if vehicle ~= nil then
1266 attacherPipeVehicle:attachPipe(attacherPipeVehicle, vehicle);
1267 end;
1268 end;
1269end;
1270
1271function Fillable.findAttacherPipeVehicle(currentVehicle, lookForPipeRef)
1272 if lookForPipeRef then
1273 if currentVehicle.attacherPipeRef ~= nil and currentVehicle.attacherPipeRefVehicle == nil then
1274 return currentVehicle;
1275 end;
1276 else
1277 if currentVehicle.attacherPipe ~= nil and currentVehicle.attacherPipeVehicle == nil then
1278 return currentVehicle;
1279 end;
1280 end;
1281 for _,implement in pairs(currentVehicle.attachedImplements) do
1282 if implement.object ~= nil then
1283 local ret = Fillable.findAttacherPipeVehicle(implement.object, lookForPipeRef);
1284 if ret ~= nil then
1285 return ret;
1286 end
1287 end
1288 end
1289 return nil;
1290end
Copyright (c) 2008-2015 GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de
Script Dokumentation Übersicht