LUADOC - Farming Simulator 17

Printable Version

Script v1.4.4.0

Engine v7.0.0.2

Foundation Reference

TensionBelts

Description
Class for vehicle which can dynamically mount objects (e.g. bales and pallets)
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
23function TensionBelts.prerequisitesPresent(specializations)
24 return true
25end

load

Description
Called on loading
Definition
load(table savegame)
Arguments
tablesavegamesavegame
Code
30function TensionBelts:load(savegame)
31 self.belts = {}
32
33 self.createTensionBelt = TensionBelts.createTensionBelt
34 self.removeTensionBelt = TensionBelts.removeTensionBelt
35 self.setTensionBeltsActive = TensionBelts.setTensionBeltsActive
36 self.objectOverlapCallback = TensionBelts.objectOverlapCallback
37 self.getObjectToMount = TensionBelts.getObjectToMount
38 self.getObjectsToUnmount = TensionBelts.getObjectsToUnmount
39 self.updateFastenState = TensionBelts.updateFastenState
40 self.refreshTensionBelts = TensionBelts.refreshTensionBelts
41 self.freeTensionBeltObject = TensionBelts.freeTensionBeltObject
42 self.lockTensionBeltObject = TensionBelts.lockTensionBeltObject
43
44 self.getIsPlayerInTensionBeltsRange = Utils.overwrittenFunction(self.getIsPlayerInTensionBeltsRange, TensionBelts.getIsPlayerInTensionBeltsRange)
45
46 self.tensionBeltsActivatable = TensionBeltsActivatable:new(self)
47
48 self.tensionBeltTotalInteractionRadius = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.tensionBelts#totalInteractionRadius"), 6)
49 self.tensionBeltInteractionRadius = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.tensionBelts#interactionRadius"), 1)
50 self.interactionBaseNode = Utils.getNoNil(Utils.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.tensionBelts#interactionBasenode")), self.rootNode)
51 self.checkSizeOffsets = {0*0.5, 5*0.5, 3*0.5}
52
53 local tensionBeltType = Utils.getNoNil(getXMLString(self.xmlFile, "vehicle.tensionBelts#tensionBeltType"), "basic")
54 local beltData = TensionBeltUtil.getBeltData(tensionBeltType)
55 if beltData == nil then
56 beltData = TensionBeltUtil.defaultBeltData
57 end
58
59 if beltData ~= nil then
60 self.tensionBelts = {}
61 self.tensionBelts.singleBelts = {}
62 self.tensionBelts.sortedBelts = {}
63 self.tensionBelts.width = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.tensionBelts#width"), 0.15)
64 self.tensionBelts.ratchetPosition = getXMLFloat(self.xmlFile, "vehicle.tensionBelts#ratchetPosition")
65 self.tensionBelts.useHooks = Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.tensionBelts#useHooks"), true)
66 self.tensionBelts.maxEdgeLength = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.tensionBelts#maxEdgeLength"), 0.1)
67 self.tensionBelts.geometryBias = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.tensionBelts#geometryBias"), 0.01)
68 self.tensionBelts.defaultOffsetSide = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.tensionBelts#defaultOffsetSide"), 0.1)
69 self.tensionBelts.defaultOffset = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.tensionBelts#defaultOffset"), 0)
70 self.tensionBelts.defaultHeight = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.tensionBelts#defaultHeight"), 5)
71 self.tensionBelts.beltData = beltData
72 self.tensionBelts.linkNode = Utils.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.tensionBelts#linkNode"))
73 self.tensionBelts.rootNode = Utils.getNoNil(Utils.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.tensionBelts#rootNode")), self.components[1].node)
74 self.tensionBelts.jointNode = Utils.getNoNil(Utils.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.tensionBelts#jointNode")), self.tensionBelts.rootNode)
75 self.tensionBelts.checkTimerDuration = 500
76 self.tensionBelts.checkTimer = self.tensionBelts.checkTimerDuration
77
78 if getRigidBodyType(self.tensionBelts.jointNode) ~= "Dynamic" and getRigidBodyType(self.tensionBelts.jointNode) ~= "Kinematic" then
79 print("Error: Given jointNode '"..getName(self.tensionBelts.jointNode).."' has invalid rigidBodyType. Have to be 'Dynamic' or 'Kinematic'! Using '"..getName(self.components[1].node).."' instead!")
80 self.tensionBelts.jointNode = self.components[1].node
81 end
82
83 local rigidBodyType = getRigidBodyType(self.tensionBelts.jointNode)
84 self.tensionBelts.isDynamic = rigidBodyType == "Dynamic"
85
86 local i = 0
87 while true do
88 local key = string.format("vehicle.tensionBelts.tensionBelt(%d)", i)
89 if not hasXMLProperty(self.xmlFile, key) then
90 break
91 end
92
93 if #self.tensionBelts.sortedBelts == 2^TensionBelts.NUM_SEND_BITS then
94 print("Warning: Max number of tension belts is ".. 2^TensionBelts.NUM_SEND_BITS.."!")
95 break
96 end
97
98 local startNode = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key.."#startNode"))
99 local endNode = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key.."#endNode"))
100 if startNode ~= nil and endNode ~= nil then
101 local x,y,_ = localToLocal(endNode, startNode, 0, 0, 0)
102
103 if math.abs(x) < 0.0001 and math.abs(y) < 0.0001 then
104 if self.tensionBelts.linkNode == nil then
105 self.tensionBelts.linkNode = getParent(startNode)
106 end
107 if self.tensionBelts.startNode == nil then
108 self.tensionBelts.startNode = startNode
109 end
110 self.tensionBelts.endNode = endNode
111
112 local offsetLeft = getXMLFloat(self.xmlFile, key.."#offsetLeft")
113 local offsetRight = getXMLFloat(self.xmlFile, key.."#offsetRight")
114 local offset = getXMLFloat(self.xmlFile, key.."#offset")
115 local height = getXMLFloat(self.xmlFile, key.."#height")
116
117 local intersectionNodes = {}
118 local j = 0
119 while true do
120 local intersectionKey = string.format(key..".intersectionNode(%d)", j)
121 if not hasXMLProperty(self.xmlFile, intersectionKey) then
122 break
123 end
124 local node = Utils.indexToObject(self.components, getXMLString(self.xmlFile, intersectionKey.."#node"))
125 if node ~= nil then
126 table.insert(intersectionNodes, node)
127 end
128 j = j + 1
129 end
130
131 local belt = {id=i+1, startNode=startNode, endNode=endNode, offsetLeft=offsetLeft, offsetRight=offsetRight, offset=offset, height=height, mesh=nil, intersectionNodes=intersectionNodes, dummy=nil, objectsToMount=nil}
132 self.tensionBelts.singleBelts[belt] = belt
133 table.insert(self.tensionBelts.sortedBelts, belt)
134 else
135 print("Warning: x and y position of endNode need to be 0 for tension belt '"..key.."' in '"..self.configFileName.."'!")
136 end
137 end
138
139 i = i + 1
140 end
141
142 local minX, minZ = math.huge, math.huge
143 local maxX, maxZ = -math.huge, -math.huge
144 for _, belt in pairs(self.tensionBelts.singleBelts) do
145 local sx,_,sz = localToLocal(belt.startNode, self.interactionBaseNode, 0, 0, 0)
146 local ex,_,ez = localToLocal(belt.endNode, self.interactionBaseNode, 0, 0, 0)
147 minX = math.min(minX, sx, ex)
148 minZ = math.min(minZ, sz, ez)
149 maxX = math.max(maxX, sx, ex)
150 maxZ = math.max(maxZ, sz, ez)
151 end
152
153 self.interactionBasePointX = (maxX + minX) / 2
154 self.interactionBasePointZ = (maxZ + minZ) / 2
155
156 for _, belt in pairs(self.tensionBelts.singleBelts) do
157 local sx,_,sz = localToLocal(belt.startNode, self.interactionBaseNode, 0, 0, 0)
158 local sl = Utils.vector2Length(self.interactionBasePointX-sx, self.interactionBasePointZ-sz)+1
159 local el = Utils.vector2Length(self.interactionBasePointX-sx, self.interactionBasePointZ-sz)+1
160 self.tensionBeltTotalInteractionRadius = math.max(self.tensionBeltTotalInteractionRadius, sl, el)
161 end
162 else
163 print("Warning: No belt data found for tension belts in '"..self.configFileName.."'!")
164 end
165
166 self.checkBoxes = {}
167 self.objectsToJoint = {}
168 self.isPlayerInTensionBeltRange = false
169 self.currentBelt = nil
170
171 self.areBeltsFasten = false
172end

postLoad

Description
Called after loading
Definition
postLoad(table savegame)
Arguments
tablesavegamesavegame
Code
177function TensionBelts:postLoad(savegame)
178 if savegame ~= nil then
179 self.beltsToLoad = {}
180 local i = 0
181 while true do
182 local key = string.format(savegame.key..".tensionBelt(%d)", i)
183 if not hasXMLProperty(savegame.xmlFile, key) then
184 break
185 end
186 if getXMLBool(savegame.xmlFile, key.."#isActive") then
187 table.insert(self.beltsToLoad, i+1)
188 end
189 i = i + 1
190 end
191 end
192end

getSaveAttributesAndNodes

Description
Returns attributes and nodes to save
Definition
getSaveAttributesAndNodes(table nodeIdent)
Arguments
tablenodeIdentnode ident
Return Values
stringattributesattributes
stringnodesnodes
Code
199function TensionBelts:getSaveAttributesAndNodes(nodeIdent)
200 local attributes = ''
201 local nodes = ""
202
203 local beltNum = 0
204 for _, belt in pairs(self.tensionBelts.sortedBelts) do
205 if beltNum > 0 then
206 nodes = nodes .."\n"
207 end
208 nodes = nodes .. nodeIdent..' <tensionBelt isActive="'..tostring(belt.mesh ~= nil)..'" />'
209
210 beltNum = beltNum + 1
211 end
212
213 return attributes, nodes
214end

delete

Description
Called on deleting
Definition
delete()
Code
218function TensionBelts:delete()
219 self.isPlayerInTensionBeltRange = false
220 g_currentMission:removeActivatableObject(self.tensionBeltsActivatable)
221 self:setTensionBeltsActive(false, nil, true)
222end

readStream

Description
Called on client side on join
Definition
readStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
234function TensionBelts:readStream(streamId, connection)
235 if self.tensionBelts ~= nil then
236 self.beltsToLoad = {}
237 for k, _ in ipairs(self.tensionBelts.sortedBelts) do
238 local beltActive = streamReadBool(streamId)
239 if beltActive then
240 table.insert(self.beltsToLoad, k)
241 end
242 end
243 end
244end

writeStream

Description
Called on server side on join
Definition
writeStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
250function TensionBelts:writeStream(streamId, connection)
251 if self.tensionBelts ~= nil then
252 for _, belt in ipairs(self.tensionBelts.sortedBelts) do
253 streamWriteBool(streamId, belt.mesh ~= nil)
254 end
255 end
256end

update

Description
Called on update
Definition
update(float dt)
Arguments
floatdttime since last call in ms
Code
261function TensionBelts:update(dt)
262
263 local currentBelt = nil
264 self.isPlayerInTensionBeltRange, currentBelt = self:getIsPlayerInTensionBeltsRange()
265
266 if self.isPlayerInTensionBeltRange then
267 if currentBelt ~= self.currentBelt then
268 if self.currentBelt ~= nil and self.currentBelt.dummy ~= nil then
269 delete(self.currentBelt.dummy)
270 self.currentBelt.dummy = nil
271 end
272 self.currentBelt = currentBelt
273
274 if self.currentBelt ~= nil and self.currentBelt.mesh == nil then
275 local objects, _ = self:getObjectToMount(self.currentBelt)
276 self:createTensionBelt(self.currentBelt, true, objects)
277 end
278 end
279 g_currentMission:addActivatableObject(self.tensionBeltsActivatable);
280 else
281 g_currentMission:removeActivatableObject(self.tensionBeltsActivatable)
282 if self.currentBelt ~= nil and self.currentBelt.dummy ~= nil then
283 delete(self.currentBelt.dummy)
284 self.currentBelt.dummy = nil
285 self.currentBelt = nil
286 end
287
288 end
289
290 if self.beltsToLoad ~= nil then
291 for _, k in pairs(self.beltsToLoad) do
292 local noEventSent = false
293 if not self.isServer then
294 -- do not resend event to server after sync. Only send event after loading to make sure client have visible tension belts
295 noEventSent = true
296 end
297 self:setTensionBeltsActive(true, self.tensionBelts.sortedBelts[k].id, noEventSent)
298 end
299 self.beltsToLoad = nil
300 end
301
302 if self:getIsActiveForInput() then
303 if InputBinding.hasEvent(InputBinding.TOGGLE_TENSION_BELTS) then
304 local newState = not self.areBeltsFasten
305 for _, belt in pairs(self.tensionBelts.sortedBelts) do
306 self:setTensionBeltsActive(newState, belt.id, false)
307 end
308 self.checkBoxes = {}
309 end
310 end
311
312 if TensionBelts.debugRendering then
313 for belt,_ in pairs(self.belts) do
314 DebugUtil.drawDebugNode(belt)
315 for i=0, getNumOfChildren(belt)-1 do
316 DebugUtil.drawDebugNode(getChildAt(belt, i))
317 end
318 end
319
320 if self.checkBoxes ~= nil then
321 for _, box in pairs(self.checkBoxes) do
322 local p = box.points
323 local c = box.color
324
325 -- bottom
326 drawDebugLine(p[1][1],p[1][2],p[1][3], c[1],c[2],c[3], p[2][1],p[2][2],p[2][3], c[1],c[2],c[3])
327 drawDebugLine(p[2][1],p[2][2],p[2][3], c[1],c[2],c[3], p[3][1],p[3][2],p[3][3], c[1],c[2],c[3])
328 drawDebugLine(p[3][1],p[3][2],p[3][3], c[1],c[2],c[3], p[4][1],p[4][2],p[4][3], c[1],c[2],c[3])
329 drawDebugLine(p[4][1],p[4][2],p[4][3], c[1],c[2],c[3], p[1][1],p[1][2],p[1][3], c[1],c[2],c[3])
330 -- top
331 drawDebugLine(p[5][1],p[5][2],p[5][3], c[1],c[2],c[3], p[6][1],p[6][2],p[6][3], c[1],c[2],c[3])
332 drawDebugLine(p[6][1],p[6][2],p[6][3], c[1],c[2],c[3], p[7][1],p[7][2],p[7][3], c[1],c[2],c[3])
333 drawDebugLine(p[7][1],p[7][2],p[7][3], c[1],c[2],c[3], p[8][1],p[8][2],p[8][3], c[1],c[2],c[3])
334 drawDebugLine(p[8][1],p[8][2],p[8][3], c[1],c[2],c[3], p[5][1],p[5][2],p[5][3], c[1],c[2],c[3])
335 -- left
336 drawDebugLine(p[1][1],p[1][2],p[1][3], c[1],c[2],c[3], p[5][1],p[5][2],p[5][3], c[1],c[2],c[3])
337 drawDebugLine(p[4][1],p[4][2],p[4][3], c[1],c[2],c[3], p[8][1],p[8][2],p[8][3], c[1],c[2],c[3])
338 -- right
339 drawDebugLine(p[2][1],p[2][2],p[2][3], c[1],c[2],c[3], p[6][1],p[6][2],p[6][3], c[1],c[2],c[3])
340 drawDebugLine(p[3][1],p[3][2],p[3][3], c[1],c[2],c[3], p[7][1],p[7][2],p[7][3], c[1],c[2],c[3])
341 drawDebugPoint(p[9][1], p[9][2], p[9][3], 1, 1, 1, 1)
342 end
343 end
344
345 local a,b,c = localToWorld(self.interactionBaseNode, self.interactionBasePointX, 0, self.interactionBasePointZ)
346 drawDebugPoint(a,b,c, 0,0,1, 1,1,1,1)
347
348 for i=0, 360-10, 10 do
349 local x,y,z = localToWorld(self.interactionBaseNode, self.interactionBasePointX+math.cos(math.rad(i))*self.tensionBeltTotalInteractionRadius,0, self.interactionBasePointZ+math.sin(math.rad(i))*self.tensionBeltTotalInteractionRadius)
350 drawDebugPoint(x, y, z, 1,1,1,1)
351 for _, belt in pairs(self.tensionBelts.singleBelts) do
352 local x,y,z = localToWorld(belt.startNode, math.cos(math.rad(i))*self.tensionBeltInteractionRadius, 0, math.sin(math.rad(i))*self.tensionBeltInteractionRadius)
353 drawDebugPoint(x, y, z, 0,1,0,1)
354 local x,y,z = localToWorld(belt.endNode, math.cos(math.rad(i))*self.tensionBeltInteractionRadius, 0, math.sin(math.rad(i))*self.tensionBeltInteractionRadius)
355 drawDebugPoint(x, y, z, 1,0,0,1)
356 end
357 end
358 end
359end

updateTick

Description
Called on update tick
Definition
updateTick(float dt)
Arguments
floatdttime since last call in ms
Code
364function TensionBelts:updateTick(dt)
365 if self.isServer and self.tensionBelts ~= nil then
366 self.tensionBelts.checkTimer = self.tensionBelts.checkTimer - dt
367 if self.tensionBelts.checkTimer < 0 then
368 -- check if entities have been deleted
369 local needUpdate = false
370 for phyiscObject, _ in pairs(self.objectsToJoint) do
371 if not entityExists(phyiscObject) then
372 self.objectsToJoint[phyiscObject] = nil
373 needUpdate = true
374 break
375 end
376 end
377 if needUpdate then
378 self:refreshTensionBelts()
379 end
380
381 self.tensionBelts.checkTimer = self.tensionBelts.checkTimerDuration
382 end
383 end
384end

draw

Description
Called on draw
Definition
draw()
Code
388function TensionBelts:draw()
389 if self.isClient and self:getIsActiveForInput() then
390 if self.areBeltsFasten then
391 g_currentMission:addHelpButtonText(g_i18n:getText("action_unfastenTensionBelts"), InputBinding.TOGGLE_TENSION_BELTS, nil, GS_PRIO_NORMAL)
392 else
393 g_currentMission:addHelpButtonText(g_i18n:getText("action_fastenTensionBelts"), InputBinding.TOGGLE_TENSION_BELTS, nil, GS_PRIO_NORMAL)
394 end
395 end
396end

setTensionBeltsActive

Description
Set tensionbelts active state
Definition
setTensionBeltsActive(boolean isActive, integer beltId)
Arguments
booleanisActivenew active state
integerbeltIdid of belt to set state (if id is nil it uses every belt)
Code
494function TensionBelts:setTensionBeltsActive(isActive, beltId, noEventSend)
495 if self.tensionBelts ~= nil then
496 TensionBeltsEvent.sendEvent(self, isActive, beltId, noEventSend)
497
498 local belt = nil
499 if beltId ~= nil then
500 belt = self.tensionBelts.sortedBelts[beltId]
501 end
502
503 if isActive then
504 local objects, _ = self:getObjectToMount(belt)
505 if belt == nil then
506 for _, belt in pairs(self.tensionBelts.singleBelts) do
507 if belt.mesh == nil then
508 self:createTensionBelt(belt, false, objects)
509 end
510 end
511 else
512 if belt.mesh == nil then
513 self:createTensionBelt(belt, false, objects)
514 end
515 end
516
517 if self.isServer then
518 for _, object in pairs(objects) do
519 self:lockTensionBeltObject(object.physics, self.objectsToJoint, self.tensionBelts.isDynamic, self.tensionBelts.jointNode)
520 end
521 end
522 else
523 if belt == nil then
524 for _, belt in pairs(self.tensionBelts.singleBelts) do
525 self:removeTensionBelt(belt)
526 end
527 else
528 self:removeTensionBelt(belt)
529 end
530
531 if self.isServer then
532 -- remove joints
533 local objectIds, _ = self:getObjectsToUnmount(belt)
534 for _, objectId in pairs(objectIds) do
535 self:freeTensionBeltObject(objectId, self.objectsToJoint, self.tensionBelts.isDynamic)
536 end
537 end
538 end
539
540 self:updateFastenState()
541 end
542end

updateFastenState

Description
Update 'self.areBeltsFasten'
Definition
updateFastenState()
Code
546function TensionBelts:updateFastenState()
547 local unfastenBelts = false
548 for _, belt in pairs(self.tensionBelts.singleBelts) do
549 if belt.mesh == nil then
550 unfastenBelts = true
551 break
552 end
553 end
554
555 self.areBeltsFasten = not unfastenBelts
556end

createTensionBelt

Description
Create tension belt
Definition
createTensionBelt(table belt, boolean isDummy, table object)
Arguments
tablebeltbelt to use
booleanisDummycreate dummy belt
tableobjectobjects to fasten
Code
563function TensionBelts:createTensionBelt(belt, isDummy, objects)
564 local tensionBelt = TensionBeltGeometryConstructor:new()
565
566 local beltData = self.tensionBelts.beltData
567
568 tensionBelt:setWidth(self.tensionBelts.width)
569 tensionBelt:setMaxEdgeLength(self.tensionBelts.maxEdgeLength)
570 if isDummy then
571 tensionBelt:setMaterial(beltData.dummyMaterial.materialId)
572 tensionBelt:setUVscale(beltData.dummyMaterial.uvScale)
573 else
574 tensionBelt:setMaterial(beltData.material.materialId)
575 tensionBelt:setUVscale(beltData.material.uvScale)
576 end
577
578 if self.tensionBelts.ratchetPosition ~= nil and beltData.ratchet ~= nil then
579 tensionBelt:addAttachment(0, self.tensionBelts.ratchetPosition, beltData.ratchet.sizeRatio*self.tensionBelts.width)
580 end
581
582 if self.tensionBelts.useHooks and beltData.hook ~= nil then
583 tensionBelt:addAttachment(0, 0, beltData.hook.sizeRatio*self.tensionBelts.width)
584 tensionBelt:addAttachment(1, 0, beltData.hook.sizeRatio*self.tensionBelts.width)
585 end
586
587 tensionBelt:setFixedPoints(belt.startNode, belt.endNode)
588 tensionBelt:setGeometryBias(self.tensionBelts.geometryBias)
589 tensionBelt:setLinkNode(self.tensionBelts.linkNode)
590
591 for _, pointNode in pairs(belt.intersectionNodes) do
592 local x,y,z = getWorldTranslation(pointNode)
593 local dirX, dirY, dirZ = localDirectionToWorld(pointNode, 1, 0, 0)
594 tensionBelt:addIntersectionPoint(x,y,z, dirX, dirY, dirZ)
595 end
596
597 for _, object in pairs(objects) do
598 for _, node in pairs(object.visuals) do
599 tensionBelt:addShape(node, 0, 1, 0, 1)
600 end
601 end
602
603 local beltShape, _, beltLength = tensionBelt:finalize()
604 if beltShape ~= 0 then
605 if isDummy then
606 belt.dummy = beltShape
607 else
608 local currentIndex = 0
609 if self.tensionBelts.ratchetPosition ~= nil and beltData.ratchet ~= nil then
610 if getNumOfChildren(beltShape) > currentIndex then
611 local scale = self.tensionBelts.width
612 local ratched = clone(beltData.ratchet.node, false, false, false)
613 link(getChildAt(beltShape, 0), ratched)
614 setScale(ratched, scale, scale, scale)
615 currentIndex = currentIndex + 1
616 end
617 end
618 if self.tensionBelts.useHooks then
619 if beltData.hook ~= nil and getNumOfChildren(beltShape) > currentIndex+1 then
620 local scale = self.tensionBelts.width
621 local hookStart = clone(beltData.hook.node, false, false, false)
622 link(getChildAt(beltShape, currentIndex), hookStart)
623 setScale(hookStart, scale, scale, scale)
624
625 local hookEnd = clone(beltData.hook.node, false, false, false)
626 link(getChildAt(beltShape, currentIndex+1), hookEnd)
627 setRotation(hookEnd, 0, math.pi, 0)
628 setTranslation(hookEnd, 0, 0, beltData.hook.sizeRatio*self.tensionBelts.width)
629 setScale(hookEnd, scale, scale, scale)
630 currentIndex = currentIndex + 2
631
632 setShaderParameter(beltShape, "beltClipOffsets", 0, beltData.hook.sizeRatio*self.tensionBelts.width, beltLength-beltData.hook.sizeRatio*self.tensionBelts.width, beltLength, false)
633 end
634 end
635
636 belt.mesh = beltShape
637 self.belts[beltShape] = beltShape
638 if belt.dummy ~= nil then
639 delete(belt.dummy)
640 belt.dummy = nil
641 end
642 end
643
644 return beltShape
645 end
646
647 return nil
648end

removeTensionBelt

Description
Remove tension belt
Definition
removeTensionBelt(table belt)
Arguments
tablebeltbelt to remove
Code
653function TensionBelts:removeTensionBelt(belt)
654 if belt.mesh ~= nil then
655 self.belts[belt.mesh] = nil
656 delete(belt.mesh)
657 belt.mesh = nil
658 if self.currentBelt == belt then
659 self.currentBelt = nil
660 end
661 end
662end

getObjectToMount

Description
Returns objects in belt range
Definition
getObjectToMount(table belt)
Arguments
tablebeltbelt to check
Return Values
tableobjectsInTensionBeltRangeobject in belt range
integernumObjectsIntensionBeltRangenumber of objects in belt range
Code
669function TensionBelts:getObjectToMount(belt)
670
671 local markerStart = self.tensionBelts.startNode
672 local markerEnd = self.tensionBelts.endNode
673 local offsetLeft = nil
674 local offsetRight = nil
675 local offset = nil
676 local height = nil
677 if belt ~= nil then
678 markerStart = belt.startNode
679 markerEnd = belt.endNode
680
681 offsetLeft = belt.offsetLeft
682 offsetRight = belt.offsetRight
683 offset = belt.offset
684 height = belt.height
685 if offsetLeft == nil then
686 if self.tensionBelts.sortedBelts[belt.id-1] ~= nil and self.tensionBelts.sortedBelts[belt.id-1].mesh ~= nil then
687 local x,_,_ = localToLocal(markerStart, self.tensionBelts.sortedBelts[belt.id-1].startNode, 0, 0, 0)
688 offsetLeft = math.abs(x)
689 end
690 end
691 if offsetRight == nil then
692 if self.tensionBelts.sortedBelts[belt.id+1] ~= nil and self.tensionBelts.sortedBelts[belt.id+1].mesh ~= nil then
693 local x,_,_ = localToLocal(markerStart, self.tensionBelts.sortedBelts[belt.id+1].startNode, 0, 0, 0)
694 offsetRight = math.abs(x)
695 end
696 end
697
698 end
699
700 if offsetLeft == nil then
701 offsetLeft = self.tensionBelts.defaultOffsetSide
702 end
703 if offsetRight == nil then
704 offsetRight = self.tensionBelts.defaultOffsetSide
705 end
706 if offset == nil then
707 offset = self.tensionBelts.defaultOffset
708 end
709 if height == nil then
710 height = self.tensionBelts.defaultHeight
711 end
712
713 local sizeX = (offsetLeft+offsetRight) * 0.5
714 local sizeY = height * 0.5
715 local _, _, width = localToLocal(markerEnd, markerStart, 0, 0, 0)
716 local sizeZ = width*0.5 - 2*offset
717
718 local centerX = (offsetLeft-offsetRight)*0.5
719 local centerY = height*0.5
720 local centerZ = width*0.5
721 local x,y,z = localToWorld(markerStart, centerX, centerY, centerZ)
722
723 if TensionBelts.debugRendering then
724 local box = {}
725 box.points = {}
726 local colorR = math.random(0, 1)
727 local colorG = math.random(0, 1)
728 local colorB = math.random(0, 1)
729 box.color = {colorR,colorG,colorB}
730
731 local blx, bly, blz = localToWorld(markerStart, centerX-sizeX, centerY-sizeY, centerZ-sizeZ)
732 local brx, bry, brz = localToWorld(markerStart, centerX+sizeX, centerY-sizeY, centerZ-sizeZ)
733 local flx, fly, flz = localToWorld(markerStart, centerX-sizeX, centerY-sizeY, centerZ+sizeZ)
734 local frx, fry, frz = localToWorld(markerStart, centerX+sizeX, centerY-sizeY, centerZ+sizeZ)
735
736 local tblx, tbly, tblz = localToWorld(markerStart, centerX-sizeX, centerY+sizeY, centerZ-sizeZ)
737 local tbrx, tbry, tbrz = localToWorld(markerStart, centerX+sizeX, centerY+sizeY, centerZ-sizeZ)
738 local tflx, tfly, tflz = localToWorld(markerStart, centerX-sizeX, centerY+sizeY, centerZ+sizeZ)
739 local tfrx, tfry, tfrz = localToWorld(markerStart, centerX+sizeX, centerY+sizeY, centerZ+sizeZ)
740
741 table.insert(box.points, { blx, bly, blz } ) -- lower: lb
742 table.insert(box.points, { brx, bry, brz } ) -- rb
743 table.insert(box.points, { frx, fry, frz } ) -- rf
744 table.insert(box.points, { flx, fly, flz } ) -- lf
745
746 table.insert(box.points, { tblx, tbly, tblz } ) -- upper: lb
747 table.insert(box.points, { tbrx, tbry, tbrz } ) -- rb
748 table.insert(box.points, { tfrx, tfry, tfrz } ) -- rf
749 table.insert(box.points, { tflx, tfly, tflz } ) -- lf
750 table.insert(box.points, { x, y, z } ) -- center
751
752 self.checkBoxes[markerStart] = box
753 end
754
755 local rx,ry,rz = getWorldRotation(markerStart)
756 self.objectsInTensionBeltRange = {}
757 self.numObjectsIntensionBeltRange = 0
758
759 -- collision mask : all bits except bit 13, 23, 30
760 overlapBox(x, y, z, rx, ry, rz, sizeX, sizeY, sizeZ, "objectOverlapCallback", self, 3212828671, true, false, true)
761
762 return self.objectsInTensionBeltRange, self.numObjectsIntensionBeltRange
763end

getObjectsToUnmount

Description
Returns objects to unmount if given belt will be removed
Definition
getObjectsToUnmount(table belt)
Arguments
tablebeltbelt to check
Return Values
tableobjectIdsToUnmounttable with object ids to unmount
integernumObjectsnumber of objects to unmount
Code
770function TensionBelts:getObjectsToUnmount(belt)
771 local objectIdsToUnmount = {}
772 local numObjects = 0
773 -- copy mounted objects table
774 for objectId, _ in pairs(self.objectsToJoint) do
775 objectIdsToUnmount[objectId] = objectId
776 numObjects = numObjects + 1
777 end
778
779 -- remove objects mounted by other active belts
780 for _, otherBelt in pairs(self.tensionBelts.singleBelts) do
781 if otherBelt.mesh ~= nil and otherBelt ~= belt then
782 local objectToMount,_ = self:getObjectToMount(otherBelt)
783 for _, object in pairs(objectToMount) do
784 -- remove objects mounted by other belts
785 if objectIdsToUnmount[object.physics] ~= nil then
786 objectIdsToUnmount[object.physics] = nil
787 numObjects = numObjects - 1
788 end
789 end
790 end
791 end
792
793 return objectIdsToUnmount, numObjects
794end

objectOverlapCallback

Description
Overlap callback
Definition
objectOverlapCallback(integer transformId)
Arguments
integertransformIdid of found transform
Code
799function TensionBelts:objectOverlapCallback(transformId)
800 if transformId ~= 0 and getHasClassId(transformId, ClassIds.SHAPE) then
801 local object = g_currentMission:getNodeObject(transformId)
802 if object ~= nil then
803 if object.getMeshNodes ~= nil and object.dynamicMountObject == nil and self.objectsInTensionBeltRange[object.nodeId] == nil then
804 local nodes = object:getMeshNodes()
805 if nodes ~= nil then
806 self.objectsInTensionBeltRange[object.nodeId] = {physics=object.nodeId, visuals=nodes}
807 self.numObjectsIntensionBeltRange = self.numObjectsIntensionBeltRange + 1
808 end
809 end
810 elseif getSplitType(transformId) ~= 0 then
811 local rigidBodyType = getRigidBodyType(transformId)
812 if (rigidBodyType == "Dynamic" or rigidBodyType == "Kinematic") and self.objectsInTensionBeltRange[transformId] == nil then
813 self.objectsInTensionBeltRange[transformId] = {physics=transformId, visuals={transformId}}
814 self.numObjectsIntensionBeltRange = self.numObjectsIntensionBeltRange + 1
815 end
816 end
817 end
818
819 return true
820end

getIsPlayerInTensionBeltsRange

Description
Returns if player is in tension belt range
Definition
getIsPlayerInTensionBeltsRange()
Return Values
booleaninRangeplayer is in range
tablebeltnearest belt
Code
826function TensionBelts:getIsPlayerInTensionBeltsRange(superFunc)
827 if superFunc ~= nil then
828 local isInRange, belt = superFunc(self)
829 if not isInRange then
830 return false, belt
831 end
832 end
833
834 if g_currentMission.player == nil then
835 return false, nil
836 end
837
838 local px, _, pz = getWorldTranslation(g_currentMission.player.rootNode)
839 local vx, _, vz = localToWorld(self.interactionBaseNode, self.interactionBasePointX, 0, self.interactionBasePointZ)
840 local currentBelt = nil
841 local distance = math.huge
842
843 if Utils.vector2Length(px-vx, pz-vz) < self.tensionBeltTotalInteractionRadius then
844 if self.tensionBelts ~= nil then
845 for _, belt in pairs(self.tensionBelts.singleBelts) do
846 local sx, _, sz = getWorldTranslation(belt.startNode)
847 local ex, _, ez = getWorldTranslation(belt.endNode)
848 local sDistance = Utils.vector2Length(px-sx, pz-sz)
849 local eDistance = Utils.vector2Length(px-ex, pz-ez)
850 if (sDistance < distance and sDistance < self.tensionBeltInteractionRadius) or (eDistance < distance and eDistance < self.tensionBeltInteractionRadius) then
851 currentBelt = belt
852 distance = math.min(sDistance, eDistance)
853 end
854 end
855 end
856
857 if distance < self.tensionBeltInteractionRadius then
858 return true, currentBelt
859 end
860 end
861
862 return false, nil
863end