LUADOC - Farming Simulator 17

Printable Version

StationCrane

Description
Class for station cranes
Functions

onCreate

Description
Creating station crane
Definition
onCreate(integer transformId)
Arguments
integertransformIdid of node
Code
15function StationCrane:onCreate(transformId)
16
17 if g_currentMission.isTutorialMission then
18 return;
19 end
20
21 local xmlFilename = getUserAttribute(transformId, "xmlFile");
22 if xmlFilename ~= nil then
23 xmlFilename = Utils.getFilename(xmlFilename, g_currentMission.loadingMapBaseDirectory);
24 local xmlFile = loadXMLFile("StationCrane", xmlFilename);
25
26 local stationCrane = StationCrane:new(g_server ~= nil, g_client ~= nil);
27 if stationCrane ~= nil then
28 -- load() will be called by OnCreateLoadedObjectsManager
29
30 stationCrane.stationCraneId = transformId;
31 stationCrane.xmlFile = xmlFile;
32 stationCrane.configFileName = xmlFilename;
33
34 g_currentMission:addOnCreateLoadedObject(stationCrane);
35
36 stationCrane:register(true);
37
38 OnCreateLoadedObjectsManager:registerObject(stationCrane);
39 end;
40 else
41 print("Error: Missing xmlFile user-attribute for station crane system in " .. getName(transformId));
42 end
43end

new

Description
Creating new instance of station crane
Definition
new(boolean isServer, boolean isClient)
Arguments
booleanisServeris server
booleanisClientis client
Return Values
tableselfnew instance of object
Code
50function StationCrane:new(isServer, isClient, customMt)
51 local mt = customMt;
52 if mt == nil then
53 mt = StationCrane_mt;
54 end
55 local self = Object:new(isServer, isClient, mt);
56
57 self.isServer = isServer;
58 self.isClient = isClient;
59
60 --
61 self.specializations = {};
62
63 return self;
64end

load

Description
Called on loading
Definition
load(table savegame)
Arguments
tablesavegamesavegame
Code
69function StationCrane:load(savegame)
70
71 local xmlNode = "vehicle";
72
73 self.rootNode = Utils.indexToObject(self.stationCraneId, "0>");
74
75 self.components = {};
76 table.insert(self.components, {node=self.rootNode, centerOfMass={0,0,0}, solverIterationCount=10});
77
78 self.propertyState = 0;
79 self.isEntered = false;
80 self.isBroken = false;
81 self.nonTabbable = false;
82 self.isControlled = false;
83
84 self.conflictCheckedInputs = {};
85
86 self.attachedImplements = {};
87 self.attacherJoints = {};
88
89 -- load components
90 local numComponents = Utils.getNoNil(getXMLInt(self.xmlFile, xmlNode..".components#count"), 0);
91 for i=1, numComponents do
92 local key = xmlNode .. string.format(".components.component%d", i);
93 if not hasXMLProperty(self.xmlFile, key) then
94 print("Warning: " .. key .. " not found in '"..self.configFileName.."'");
95 break;
96 end;
97
98 local component = {};
99 component.node = Utils.indexToObject(self.rootNode, getXMLString(self.xmlFile, key .. "#index"));
100
101 local x, y, z = Utils.getVectorFromString(getXMLString(self.xmlFile, key .. "#centerOfMass"));
102 if x ~= nil and y ~= nil and z ~= nil then
103 setCenterOfMass(component.node, x, y, z);
104 component.centerOfMass = { x, y, z };
105 end;
106
107 local count = getXMLInt(self.xmlFile, key .. "#solverIterationCount");
108 if count ~= nil then
109 setSolverIterationCount(component.node, count);
110 component.solverIterationCount = count;
111 end;
112
113 table.insert(self.components, component);
114 end
115
116 self.componentJoints = {};
117 if self.isServer then
118 local componentJointI = 0;
119 while true do
120 local key = xmlNode .. string.format(".componentJoints.componentJoint(%d)", componentJointI);
121 local index1 = getXMLInt(self.xmlFile, key.."#component1");
122 local index2 = getXMLInt(self.xmlFile, key.."#component2");
123 local jointIndexStr = getXMLString(self.xmlFile, key.."#index");
124 if index1 == nil or index2 == nil or jointIndexStr == nil then
125 break;
126 end;
127 local jointNode = Utils.indexToObject(self.components, jointIndexStr);
128 if jointNode ~= nil and jointNode ~= 0 then
129 local jointDesc = {};
130 if Vehicle.loadComponentJointFromXML(self, jointDesc, self.xmlFile, key, componentJointI, jointNode, index1, index2) then
131 table.insert(self.componentJoints, jointDesc);
132 end
133 end
134 componentJointI = componentJointI + 1;
135 end
136 end
137
138 if self.isServer then
139 for _, jointDesc in pairs(self.componentJoints) do
140 self:createComponentJoint(self.components[jointDesc.componentIndices[1]], self.components[jointDesc.componentIndices[2]], jointDesc);
141 end
142 end
143
144 local collisionPairI = 0;
145 self.collisionPairs = {}
146 while true do
147 local key = string.format("vehicle.components.collisionPair(%d)", collisionPairI);
148 if not hasXMLProperty(self.xmlFile, key) then
149 break;
150 end;
151 local enabled = getXMLBool(self.xmlFile, key.."#enabled");
152 local index1 = getXMLInt(self.xmlFile, key.."#component1");
153 local index2 = getXMLInt(self.xmlFile, key.."#component2");
154 if index1 ~= nil and index2 ~= nil and enabled ~= nil then
155 local component1 = self.components[index1+1];
156 local component2 = self.components[index2+1];
157 if component1 ~= nil and component2 ~= nil then
158 if not enabled then
159 table.insert(self.collisionPairs, {component1=component1, component2=component2, enabled=enabled})
160 setPairCollision(component1.node, component2.node, false);
161 end;
162 end;
163 end;
164 collisionPairI = collisionPairI +1;
165 end;
166
167
168 if self.isClient then
169 self.engineSample = SoundUtil.loadSample(self.xmlFile, {}, "vehicle.stationCrane.engineSound", nil, g_currentMission.loadingMapBaseDirectory, self.components[2].node);
170 end
171
172 --
173 self.ikChains = {};
174
175 self.specializations = {};
176 local i = 0;
177 while true do
178 local baseString = xmlNode .. string.format(".specializations.specialization(%d)", i);
179 if not hasXMLProperty(self.xmlFile, baseString) then
180 break;
181 end
182
183 local specName = getXMLString(self.xmlFile, baseString .. "#name");
184 local spec = SpecializationUtil.getSpecialization(specName);
185 if spec == nil then
186 print("Error: Vehicle types unknown specialization " .. specName);
187 return false;
188 end
189
190 table.insert(self.specializations, spec);
191 i = i + 1;
192 end
193
194 for _,spec in pairs(self.specializations) do
195 if spec.preLoad ~= nil then
196 local ret = spec.preLoad(self, savegame);
197 if ret ~= nil and ret ~= BaseMission.VEHICLE_LOAD_OK then
198 return ret;
199 end
200 end
201 end
202 for _,spec in pairs(self.specializations) do
203 if spec.load ~= nil then
204 local ret = spec.load(self, savegame);
205 if ret ~= nil and ret ~= BaseMission.VEHICLE_LOAD_OK then
206 return ret;
207 end
208 end
209 end
210 for _,spec in pairs(self.specializations) do
211 if spec.postLoad ~= nil then
212 -- don't apply saved values of cylindered
213 if spec ~= Cylindered then
214 local ret = spec.postLoad(self, savegame);
215 if ret ~= nil and ret ~= BaseMission.VEHICLE_LOAD_OK then
216 return ret;
217 end
218 end
219 end
220 end
221
222
223 -- link components to rootNode, after all objects have been loaded
224 for i=2, table.getn(self.components) do
225 local component = self.components[i];
226
227 local x,y,z = getWorldTranslation(component.node);
228 local rx,ry,rz = getWorldRotation(component.node);
229 local qx,qy,qz,qw = getWorldQuaternion(component.node);
230
231 link(getRootNode(), component.node);
232 setTranslation(component.node, x,y,z);
233 setRotation(component.node, rx,ry,rz);
234
235 component.sentTranslation = {x,y,z};
236 component.sentRotation = {rx,ry,rz};
237 component.lastTranslation = {x,y,z};
238 component.lastRotation = {qx,qy,qz,qw};
239 component.targetTranslation = {x,y,z};
240 component.targetRotation = {qx,qy,qz,qw};
241 component.curTranslation = {x,y,z};
242 component.curRotation = {qx,qy,qz,qw};
243
244 if not self.isServer then
245 setRigidBodyType(component.node, "Kinematic");
246 end;
247
248 end
249
250 self.interpolationAlpha = 0;
251 self.interpolationDuration = 50+30;
252 self.positionIsDirty = false;
253
254 --
255 self.stationCraneDirtyFlag = self:getNextDirtyFlag();
256
257 delete(self.xmlFile);
258 self.xmlFile = nil;
259
260 g_currentMission:addVehicle(self);
261end

delete

Description
Deleting station crane
Definition
delete()
Code
265function StationCrane:delete()
266
267 if self.isClient then
268 SoundUtil.deleteSample(self.engineSample);
269 end
270
271 -- Check if the objects has been loaded
272 if self.specializations ~= nil then
273 for i=table.getn(self.specializations), 1, -1 do
274 if self.specializations[i].preDelete ~= nil then
275 self.specializations[i].preDelete(self);
276 end
277 end
278 for i=table.getn(self.specializations), 1, -1 do
279 if self.specializations[i].delete ~= nil then
280 self.specializations[i].delete(self);
281 end
282 end
283 end
284
285 if self.isServer then
286 for _,v in pairs(self.componentJoints) do
287 if v.jointIndex ~= 0 then
288 removeJoint(v.jointIndex);
289 end
290 end;
291 end;
292
293 if self.components then
294 for _,v in pairs(self.components) do
295 delete(v.node);
296 end;
297 end;
298
299 StationCrane:superClass().delete(self);
300
301 OnCreateLoadedObjectsManager:removeObject(self);
302
303 g_currentMission:removeVehicle(self, false);
304end

getSaveAttributesAndNodes

Description
Get save attributes and nodes
Definition
getSaveAttributesAndNodes(string nodeIdent)
Arguments
stringnodeIdentnode ident
Return Values
stringattributesattributes
stringnodesnodes
Code
311function StationCrane:getSaveAttributesAndNodes(nodeIdent)
312 local attributes = "";
313 local nodes = "";
314
315 for k,v in pairs(self.specializations) do
316 if v.getSaveAttributesAndNodes ~= nil then
317 if nodes ~= '' then
318 nodes = nodes .."\n"
319 end
320 local specAttributes, specNodes = v.getSaveAttributesAndNodes(self, nodeIdent, usedModNames);
321 if specAttributes ~= nil and specAttributes ~= "" then
322 attributes = attributes.." "..specAttributes;
323 end;
324 if specNodes ~= nil and specNodes ~= "" then
325 nodes = nodes..specNodes;
326 end;
327 end;
328 end;
329
330 return attributes, nodes;
331end

readStream

Description
Called on client side on join
Definition
readStream(integer streamId, table connection)
Arguments
integerstreamIdstream ID
tableconnectionconnection
Code
337function StationCrane:readStream(streamId, connection)
338 self:load(nil);
339 for i=2, table.getn(self.components) do
340 local x=streamReadFloat32(streamId);
341 local y=streamReadFloat32(streamId);
342 local z=streamReadFloat32(streamId);
343 local x_rot=streamReadFloat32(streamId)
344 local y_rot=streamReadFloat32(streamId);
345 local z_rot=streamReadFloat32(streamId);
346 local w_rot=streamReadFloat32(streamId);
347 self:setWorldPositionQuaternion(x,y,z, x_rot,y_rot,z_rot,w_rot, i);
348
349 self.components[i].lastTranslation = {x,y,z};
350 self.components[i].lastRotation = {x_rot,y_rot,z_rot,w_rot};
351 self.components[i].targetTranslation = {x,y,z};
352 self.components[i].targetRotation = {x_rot,y_rot,z_rot,w_rot};
353 self.components[i].curTranslation = {x,y,z};
354 self.components[i].curRotation = {x_rot,y_rot,z_rot,w_rot};
355 end;
356 self.interpolationAlpha = 0;
357 self.positionIsDirty = false;
358
359 for _,spec in pairs(self.specializations) do
360 if spec.readStream ~= nil then
361 spec.readStream(self, streamId, connection);
362 end
363 end
364end

writeStream

Description
Called on server side on join
Definition
writeStream(integer streamId, table connection)
Arguments
integerstreamIdstream ID
tableconnectionconnection
Code
370function StationCrane:writeStream(streamId, connection)
371 for i=2, table.getn(self.components) do
372 local x,y,z = getTranslation(self.components[i].node);
373 local x_rot,y_rot,z_rot,w_rot = getQuaternion(self.components[i].node);
374
375 streamWriteFloat32(streamId, x);
376 streamWriteFloat32(streamId, y);
377 streamWriteFloat32(streamId, z);
378 streamWriteFloat32(streamId, x_rot);
379 streamWriteFloat32(streamId, y_rot);
380 streamWriteFloat32(streamId, z_rot);
381 streamWriteFloat32(streamId, w_rot);
382 end;
383
384 for _,spec in pairs(self.specializations) do
385 if spec.writeStream ~= nil then
386 spec.writeStream(self, streamId, connection);
387 end
388 end
389end

readUpdateStream

Description
Called on client side on update
Definition
readUpdateStream(integer streamId, integer timestamp, table connection)
Arguments
integerstreamIdstream ID
integertimestamptimestamp
tableconnectionconnection
Code
396function StationCrane:readUpdateStream(streamId, timestamp, connection)
397 if connection.isServer then
398 local hasUpdate = streamReadBool(streamId);
399 if hasUpdate then
400
401 -- We need to use g_packetPhysicsNetworkTime instead of timestamp, because we need to use the exact same time stepping as we used when simulating
402 -- Due to the async physics simulation, we always see the results of the dt of one frame behind, so physicsDt ~= dt
403
404 -- Interpolate to target from currently interpolated position
405
406 local deltaTime = g_client.tickDuration;
407 if self.lastPhysicsNetworkTime ~= nil then
408 deltaTime = math.min(g_packetPhysicsNetworkTime - self.lastPhysicsNetworkTime, 3*g_client.tickDuration);
409 end
410 self.lastPhysicsNetworkTime = g_packetPhysicsNetworkTime;
411
412 -- interpTimeLeft is the time we would've continued interpolating. This should always be about g_clientInterpDelay.
413 -- If we extrapolated, reset to the full delay
414 local interpTimeLeft = g_clientInterpDelay;
415 if self.positionIsDirty and self.interpolationAlpha < 1 then
416 interpTimeLeft = (1-self.interpolationAlpha) * self.interpolationDuration;
417 interpTimeLeft = interpTimeLeft * 0.95 + g_clientInterpDelay * 0.05; -- slighly blend towards the expected delay
418 interpTimeLeft = math.min(interpTimeLeft, 3*g_clientInterpDelay); -- clamp to some reasonable maximum
419 end
420 self.interpolationDuration = interpTimeLeft + deltaTime;
421 self.interpolationAlpha = 0;
422
423 local paramsXZ = g_currentMission.vehicleXZPosCompressionParams;
424 local paramsY = g_currentMission.vehicleYPosCompressionParams;
425 for i=2, table.getn(self.components) do -- start at index 2 !
426 local x = Utils.readCompressedWorldPosition(streamId, paramsXZ);
427 local y = Utils.readCompressedWorldPosition(streamId, paramsY);
428 local z = Utils.readCompressedWorldPosition(streamId, paramsXZ);
429 local x_rot = Utils.readCompressedAngle(streamId);
430 local y_rot = Utils.readCompressedAngle(streamId);
431 local z_rot = Utils.readCompressedAngle(streamId);
432
433 local x_rot,y_rot,z_rot,w_rot = mathEulerToQuaternion(x_rot,y_rot,z_rot);
434 local targetTranslation = self.components[i].targetTranslation;
435 local targetRotation = self.components[i].targetRotation;
436 targetTranslation[1] = x;
437 targetTranslation[2] = y;
438 targetTranslation[3] = z;
439 targetRotation[1] = x_rot; targetRotation[2] = y_rot; targetRotation[3] = z_rot; targetRotation[4] = w_rot;
440
441 local trans = self.components[i].curTranslation;
442 local rot = self.components[i].curRotation;
443 local lastTranslation = self.components[i].lastTranslation;
444 local lastRotation = self.components[i].lastRotation;
445 lastTranslation[1] = trans[1];
446 lastTranslation[2] = trans[2];
447 lastTranslation[3] = trans[3];
448 lastRotation[1] = rot[1]; lastRotation[2] = rot[2]; lastRotation[3] = rot[3]; lastRotation[4] = rot[4];
449 end;
450 self.positionIsDirty = true;
451 end
452 end
453
454 for _,spec in pairs(self.specializations) do
455 if spec.readUpdateStream ~= nil then
456 spec.readUpdateStream(self, streamId, timestamp, connection);
457 end
458 end
459end

writeUpdateStream

Description
Called on server side on update
Definition
writeUpdateStream(integer streamId, table connection, integer dirtyMask)
Arguments
integerstreamIdstream ID
tableconnectionconnection
integerdirtyMaskdirty mask
Code
466function StationCrane:writeUpdateStream(streamId, connection, dirtyMask)
467 if not connection.isServer then
468 if streamWriteBool(streamId, bitAND(dirtyMask, self.stationCraneDirtyFlag) ~= 0) then
469
470 local paramsXZ = g_currentMission.vehicleXZPosCompressionParams;
471 local paramsY = g_currentMission.vehicleYPosCompressionParams;
472 for i=2, table.getn(self.components) do
473 local x,y,z = getTranslation(self.components[i].node)
474 --local x_rot,y_rot,z_rot,w_rot=getQuaternion(self.components[i].node);
475 local x_rot,y_rot,z_rot = getRotation(self.components[i].node);
476
477 Utils.writeCompressedWorldPosition(streamId, x, paramsXZ);
478 Utils.writeCompressedWorldPosition(streamId, y, paramsY);
479 Utils.writeCompressedWorldPosition(streamId, z, paramsXZ);
480 Utils.writeCompressedAngle(streamId, x_rot);
481 Utils.writeCompressedAngle(streamId, y_rot);
482 Utils.writeCompressedAngle(streamId, z_rot);
483 end;
484 end
485 end
486
487 for _,spec in pairs(self.specializations) do
488 if spec.writeUpdateStream ~= nil then
489 spec.writeUpdateStream(self, streamId, connection, dirtyMask);
490 end
491 end
492end

keyEvent

Description
Called on key event
Definition
keyEvent(integer unicode, integer sym, integer modifier, boolean isDown)
Arguments
integerunicodeunicode
integersymsym
integermodifiermodifier
booleanisDownis button down
Code
500function StationCrane:keyEvent(unicode, sym, modifier, isDown)
501 for _,spec in pairs(self.specializations) do
502 if spec.keyEvent ~= nil then
503 spec.mouseEvent(self, unicode, sym, modifier, isDown);
504 end
505 end
506end

mouseEvent

Description
Called on mouse event
Definition
mouseEvent(float posX, float posY, boolean isDown, boolean isUp, integer button)
Arguments
floatposXx position
floatposYy position
booleanisDownis mouse button down
booleanisUpis mouse button up
integerbuttonmouse button
Code
515function StationCrane:mouseEvent(posX, posY, isDown, isUp, button)
516 for _,spec in pairs(self.specializations) do
517 if spec.mouseEvent ~= nil then
518 spec.mouseEvent(self, posX, posY, isDown, isUp, button);
519 end
520 end
521end

update

Description
Called on update
Definition
update(float dt)
Arguments
floatdttime since last call in ms
Code
526function StationCrane:update(dt)
527 StationCrane:superClass().update(self, dt);
528
529 if not self.isServer and self.positionIsDirty then
530 local maxIntrpAlpha = 1.2;
531 local interpolationAlpha = self.interpolationAlpha + g_physicsDtUnclamped / self.interpolationDuration;
532 if interpolationAlpha >= maxIntrpAlpha then
533 interpolationAlpha = maxIntrpAlpha;
534 self.positionIsDirty = false;
535 end;
536 self.interpolationAlpha = interpolationAlpha;
537 for i=2, table.getn(self.components) do
538 local lastTranslation = self.components[i].lastTranslation;
539 local targetTranslation = self.components[i].targetTranslation;
540 local curTranslation = self.components[i].curTranslation;
541 curTranslation[1] = lastTranslation[1] + interpolationAlpha * (targetTranslation[1] - lastTranslation[1]);
542 curTranslation[2] = lastTranslation[2] + interpolationAlpha * (targetTranslation[2] - lastTranslation[2]);
543 curTranslation[3] = lastTranslation[3] + interpolationAlpha * (targetTranslation[3] - lastTranslation[3]);
544 local rot1 = self.components[i].lastRotation;
545 local rot2 = self.components[i].targetRotation;
546 local x,y,z,w = Utils.nlerpQuaternionShortestPath(rot1[1], rot1[2], rot1[3], rot1[4], rot2[1], rot2[2], rot2[3], rot2[4], interpolationAlpha);
547 local curRotation = self.components[i].curRotation;
548 curRotation[1] = x; curRotation[2] = y; curRotation[3] = z; curRotation[4] = w;
549 self:setWorldPositionQuaternion(curTranslation[1], curTranslation[2], curTranslation[3], x,y,z,w, i);
550 end;
551 end;
552
553 if self.specializations ~= nil then
554 for _,spec in pairs(self.specializations) do
555 if spec.update ~= nil then
556 spec.update(self, dt);
557 end
558 end
559 end
560 if self:getIsActive() then
561 IKUtil.updateIKChains(self.ikChains);
562 end
563
564end

updateTick

Description
Called on update tick
Definition
updateTick(float dt)
Arguments
floatdttime since last call in ms
Code
569function StationCrane:updateTick(dt)
570 StationCrane:superClass().updateTick(self, dt);
571
572 if self.isServer then
573 local hasOwner = self:getOwner() ~= nil;
574 for i=2, table.getn(self.components) do
575 local x,y,z = getTranslation(self.components[i].node);
576 local x_rot,y_rot,z_rot=getRotation(self.components[i].node);
577 local sentTranslation = self.components[i].sentTranslation;
578 local sentRotation = self.components[i].sentRotation;
579 if hasOwner or
580 math.abs(x-sentTranslation[1]) > 0.005 or
581 math.abs(y-sentTranslation[2]) > 0.005 or
582 math.abs(z-sentTranslation[3]) > 0.005 or
583 math.abs(x_rot-sentRotation[1]) > 0.1 or
584 math.abs(y_rot-sentRotation[2]) > 0.1 or
585 math.abs(z_rot-sentRotation[3]) > 0.1
586 then
587 self:raiseDirtyFlags(self.stationCraneDirtyFlag);
588 sentTranslation[1] = x; sentTranslation[2] = y; sentTranslation[3] = z;
589 sentRotation[1] = x_rot; sentRotation[2] = y_rot; sentRotation[3] = z_rot;
590 self.lastMoveTime = g_currentMission.time;
591 end;
592 end;
593 end
594
595 if self.isClient then
596 if self.isControlled then
597 if self.isEntered then
598 SoundUtil.playSample(self.engineSample, 0, 0, nil);
599 SoundUtil.stop3DSample(self.engineSample);
600 else
601 SoundUtil.stopSample(self.engineSample);
602 SoundUtil.play3DSample(self.engineSample);
603 end
604 else
605 SoundUtil.stopSample(self.engineSample);
606 SoundUtil.stop3DSample(self.engineSample);
607 end
608 end;
609
610 if self.specializations then
611 for _,spec in pairs(self.specializations) do
612 if spec.updateTick ~= nil then
613 spec.updateTick(self, dt);
614 end
615 end
616 end
617end

addNodeVehicleMapping

Description
Add node to vehicle mapping
Definition
addNodeVehicleMapping(table list)
Arguments
tablelistlist
Code
625function StationCrane:addNodeVehicleMapping(list)
626 if self.components == nil then
627 return;
628 end
629
630 for k,v in pairs(self.components) do
631 list[v.node] = self;
632 end
633
634 for k,v in pairs(self.specializations) do
635 if v.addNodeVehicleMapping ~= nil then
636 v.addNodeVehicleMapping(self, list);
637 end
638 end
639end

removeNodeVehicleMapping

Description
Remove node from vehicle mapping
Definition
removeNodeVehicleMapping(table list)
Arguments
tablelistlist
Code
644function StationCrane:removeNodeVehicleMapping(list)
645 if self.components == nil then
646 return;
647 end
648
649 for k,v in pairs(self.components) do
650 list[v.node] = nil;
651 end
652
653 for k,v in pairs(self.specializations) do
654 if v.removeNodeVehicleMapping ~= nil then
655 v.removeNodeVehicleMapping(self, list);
656 end
657 end
658end

getIsActive

Description
Returns if is active
Definition
getIsActive()
Return Values
booleanisActiveis active
Code
663function StationCrane:getIsActive()
664 if self.isEntered or self.isControlled then
665 return true;
666 end
667 if self.attacherVehicle ~= nil then
668 return self.attacherVehicle:getIsActive();
669 end
670end

getIsActiveForInput

Description
Returns if is active for input
Definition
getIsActiveForInput()
Return Values
booleanisActiveis active
Code
675function StationCrane:getIsActiveForInput(onlyTrueIfSelected)
676 if g_gui:getIsGuiVisible() or g_currentMission.isPlayerFrozen then
677 return false;
678 end
679
680 if self.isEntered then
681 if onlyTrueIfSelected == nil or onlyTrueIfSelected then
682 return self.selectedImplement == nil;
683 else
684 return true;
685 end
686 end
687
688 if self.attacherVehicle ~= nil then
689 if onlyTrueIfSelected == nil or onlyTrueIfSelected then
690 return self.isSelected and self.attacherVehicle:getIsActiveForInput(false);
691 else
692 return self.attacherVehicle:getIsActiveForInput(false);
693 end
694 end
695 return false;
696end

getIsActiveForSound

Description
Returns if is active for sound
Definition
getIsActiveForSound()
Return Values
booleanisActiveis active
Code
701function StationCrane:getIsActiveForSound()
702 if self.isClient then
703 if self.isEntered then
704 return true;
705 end
706 if self.attacherVehicle ~= nil then
707 return self.attacherVehicle:getIsActiveForSound();
708 end
709 end
710 return false;
711end

getRootAttacherVehicle

Description
Returns root attacher vehicle
Definition
getRootAttacherVehicle()
Return Values
tablerootAttacherVehicleroot attacher vehicle
Code
716function StationCrane:getRootAttacherVehicle()
717 local rootVehicle = self;
718 while rootVehicle.attacherVehicle ~= nil do
719 rootVehicle = rootVehicle.attacherVehicle;
720 end
721 return rootVehicle;
722end

getAttachedTrailersFillLevelAndCapacity

Description
Returns fill level and capacity of attached trailers
Definition
getAttachedTrailersFillLevelAndCapacity()
Return Values
floatfillLevelfill level
floatcapacitycapacity
Code
728function StationCrane:getAttachedTrailersFillLevelAndCapacity()
729 local fillLevel = 0;
730 local capacity = 0;
731 local hasTrailer = false;
732
733 if self.fillLevel ~= nil and self.getCapacity ~= nil then
734 fillLevel = fillLevel + self.fillLevel;
735 capacity = capacity + self:getCapacity();
736 hasTrailer = true;
737 end
738
739 for _, implement in pairs(self.attachedImplements) do
740 if implement.object ~= nil then
741 local f, c = implement.object:getAttachedTrailersFillLevelAndCapacity();
742 if f ~= nil and c ~= nil then
743 fillLevel = fillLevel + f;
744 capacity = capacity + c;
745 hasTrailer = true;
746 end
747 end
748 end
749 if hasTrailer then
750 return fillLevel, capacity;
751 end
752 return nil;
753end

getOwner

Description
Returns owner
Definition
getOwner()
Return Values
tableownerowner
Code
758function StationCrane:getOwner()
759 if self.owner ~= nil then
760 return self.owner;
761 end
762 if self.attacherVehicle ~= nil then
763 return self.attacherVehicle:getOwner();
764 end
765 return nil;
766end

getIsHired

Description
Returns if is hired
Definition
getIsHired()
Return Values
booleanisHiredis hired
Code
771function StationCrane:getIsHired()
772 return false;
773end

getParentComponent

Description
Returns parent component
Definition
getParentComponent(integer node)
Arguments
integernodenode
Return Values
integerparentComponentparent component
Code
779function StationCrane:getParentComponent(node)
780 local parent = node;
781 while getParent(parent) ~= nil do
782 for i,component in pairs(self.components) do
783 if component.node == parent then
784 return parent;
785 end
786 end
787 parent = getParent(parent);
788 end
789 return 0;
790end

getDeactivateOnLeave

Description
Returns if deactivate on leave
Definition
getDeactivateOnLeave()
Return Values
booleandeactivateOnLeavedeactivate on leave
Code
795function StationCrane:getDeactivateOnLeave()
796 return true;
797end

getDailyUpKeep

Description
Returns daily up keep
Definition
getDailyUpKeep()
Return Values
floatdailyUpKeepdaily up keep
Code
802function StationCrane:getDailyUpKeep()
803 return 0;
804end

onActivate

Description
Called on activation
Definition
onActivate()
Code
808function StationCrane:onActivate()
809 for k,v in pairs(self.specializations) do
810 if v.onActivate ~= nil then
811 v.onActivate(self);
812 end
813 end
814end

onDeactivate

Description
Called on deactivation
Definition
onDeactivate()
Code
818function StationCrane:onDeactivate()
819 for k,v in pairs(self.specializations) do
820 if v.onDeactivate ~= nil then
821 v.onDeactivate(self);
822 end
823 end
824
825 self:onDeactivateSounds();
826end

onDeactivateSounds

Description
Called on sound deactivation
Definition
onDeactivateSounds()
Code
830function StationCrane:onDeactivateSounds()
831 for k,v in pairs(self.specializations) do
832 if v.onDeactivateSounds ~= nil then
833 v.onDeactivateSounds(self);
834 end
835 end
836end

createComponentJoint

Description
Create component joint between two components
Definition
createComponentJoint(table component1, table component2, table jointDesc)
Arguments
tablecomponent1component 1
tablecomponent2component 2
tablejointDescjoint desc
Return Values
booleansuccesssuccess
Code
844function StationCrane:createComponentJoint(component1, component2, jointDesc)
845 Vehicle.createComponentJoint(self, component1, component2, jointDesc)
846end

hasInputConflictWithSelection

Description
Returns true if input conflict with selection
Definition
hasInputConflictWithSelection(table inputs)
Arguments
tableinputsinputs
Return Values
booleanhasConflicthas conflict
Code
852function StationCrane:hasInputConflictWithSelection(inputs)
853 if inputs == nil then
854 inputs = self.conflictCheckedInputs;
855 end
856 local rootAttacherVehicle = self:getRootAttacherVehicle();
857 local curVehicle = rootAttacherVehicle;
858 if rootAttacherVehicle.selectedImplement ~= nil then
859 curVehicle = rootAttacherVehicle.selectedImplement.object;
860 end
861 -- check selected implement and all of its attachers (up to our vehicle or root) for conflicts
862 -- implements have a higher priority if they have a smaller distance to the selected implement in the tree
863 while curVehicle ~= nil and curVehicle ~= self do
864 if curVehicle:hasInputConflict(inputs, false) then
865 return true;
866 end
867 curVehicle = curVehicle.attacherVehicle;
868 end
869 -- no conflcit if we are between the selection and the root and have no conflict with implements closer to the selection
870 if curVehicle == self then
871 return false;
872 end
873
874 -- not within the selection and the root, test for conflict to all other implements
875 return rootAttacherVehicle:hasInputConflict(inputs, true, self);
876end

hasInputConflict

Description
Returns true if has input conflict
Definition
hasInputConflict(table inputs, boolean recursive, table excludedVehicle)
Arguments
tableinputsinputs
booleanrecursivecheck recursive
tableexcludedVehicleexcluded vehicle
Return Values
booleanhasConflicthas conflict
Code
884function StationCrane:hasInputConflict(inputs, recursive, excludedVehicle)
885 if next(self.conflictCheckedInputs) ~= nil and self ~= excludedVehicle then
886 for input,_ in pairs(inputs) do
887 if InputBinding.getHasInputConflict(input, self.conflictCheckedInputs) then
888 return true;
889 end
890 end
891 end
892 if recursive then
893 for _,v in pairs(self.attachedImplements) do
894 if v.object ~= nil and v.object:hasInputConflict(inputs, recursive, excludedVehicle) then
895 return true;
896 end
897 end
898 end
899 return false;
900end

addConflictCheckedInput

Description
Add conflict checked input
Definition
addConflictCheckedInput(integer actionIndex)
Arguments
integeractionIndexindex of action
Code
905function StationCrane:addConflictCheckedInput(actionIndex)
906 self.conflictCheckedInputs[actionIndex] = true;
907end

removeConflictCheckedInput

Description
Remove conflict checked input
Definition
removeConflictCheckedInput(integer actionIndex)
Arguments
integeractionIndexindex of action
Code
912function StationCrane:removeConflictCheckedInput(actionIndex)
913 self.conflictCheckedInputs[actionIndex] = nil;
914end

setComponentJointRotLimit

Description
Set component joint rot limit
Definition
setComponentJointRotLimit(integer componentJoint, integer axis, float minLimit, float maxLimit)
Arguments
integercomponentJointindex of component joint
integeraxisaxis
floatminLimitmin limit
floatmaxLimitmax limit
Code
922function StationCrane:setComponentJointRotLimit(componentJoint, axis, minLimit, maxLimit)
923 Vehicle.setComponentJointRotLimit(self, componentJoint, axis, minLimit, maxLimit)
924end

setComponentJointTransLimit

Description
Set component joint trans limit
Definition
setComponentJointTransLimit(integer componentJoint, integer axis, float minLimit, float maxLimit)
Arguments
integercomponentJointindex of component joint
integeraxisaxis
floatminLimitmin limit
floatmaxLimitmax limit
Code
932function StationCrane:setComponentJointTransLimit(componentJoint, axis, minLimit, maxLimit)
933 Vehicle.setComponentJointTransLimit(self, componentJoint, axis, minLimit, maxLimit)
934end

setWorldPositionQuaternion

Description
Set world position and quaternion rotation of component
Definition
setWorldPositionQuaternion(float x, float y, float z, float qx, float qy, float qz, float qw, integer i, boolean changeInterp)
Arguments
floatxx position
floatyy position
floatzz position
floatqxx rotation
floatqyy rotation
floatqzz rotation
floatqww rotation
integeriindex if component
booleanchangeInterpchange interpolation
Code
947function StationCrane:setWorldPositionQuaternion(x,y,z, xRot,yRot,zRot,wRot, i)
948 setTranslation(self.components[i].node, x,y,z);
949 setQuaternion(self.components[i].node, xRot,yRot,zRot,wRot);
950end;

setComponentJointFrame

Description
Set component joint frame
Definition
setComponentJointFrame(integer jointDesc, integer anchorActor)
Arguments
integerjointDescjoint desc index
integeranchorActoranchor actor
Code
956function StationCrane:setComponentJointFrame(jointDesc, anchorActor)
957 Vehicle.setComponentJointFrame(self, jointDesc, anchorActor)
958end