LUADOC - Farming Simulator 19

Script v1.7.1.0

Engine v1.7.1.0

Foundation Reference

LogGrab

Description
Specialization for log/tree trunk grab/claws provinding optimized grip
Functions

addNodeObjectMapping

Description
Definition
addNodeObjectMapping()
Code
284function LogGrab:addNodeObjectMapping(superFunc, list)
285 superFunc(self, list)
286
287 local spec = self.spec_logGrab
288 if spec.logGrabTrigger ~= nil and spec.logGrabTrigger.triggerNode ~= nil then
289 list[spec.logGrabTrigger.triggerNode] = self
290 end
291end

logGrabTriggerCallback

Description
Definition
logGrabTriggerCallback()
Code
261function LogGrab:logGrabTriggerCallback(triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId)
262 local spec = self.spec_logGrab
263
264 if onEnter then
265 if getSplitType(otherActorId) ~= 0 then
266 local rigidBodyType = getRigidBodyType(otherActorId)
267 if (rigidBodyType == "Dynamic" or rigidBodyType == "Kinematic") and spec.pendingDynamicMountShapes[otherActorId] == nil then
268 spec.pendingDynamicMountShapes[otherActorId] = true
269 end
270 end
271 elseif onLeave then
272 if getSplitType(otherActorId) ~= 0 then
273 if spec.pendingDynamicMountShapes[otherActorId] ~= nil then
274 spec.pendingDynamicMountShapes[otherActorId] = nil
275 elseif spec.dynamicMountedShapes[otherActorId] ~= nil then
276 self:unmountSplitShape(otherActorId, spec.dynamicMountedShapes[otherActorId].jointIndex, spec.dynamicMountedShapes[otherActorId].jointTransform, true)
277 end
278 end
279 end
280end

mountSplitShape

Description
Definition
mountSplitShape()
Code
216function LogGrab:mountSplitShape(shapeId)
217 local spec = self.spec_logGrab
218
219 local constr = JointConstructor:new()
220 constr:setActors(spec.jointRoot, shapeId)
221
222 local jointTransform = createTransformGroup("dynamicMountJoint")
223 link(spec.jointNode, jointTransform)
224
225 constr:setJointTransforms(jointTransform, jointTransform)
226
227 constr:setRotationLimit(0, 0, 0)
228 constr:setRotationLimit(1, 0, 0)
229 constr:setRotationLimit(2, 0, 0)
230 if not spec.lockAllAxis then
231 constr:setTranslationLimit(1, false, 0, 0)
232 constr:setTranslationLimit(2, false, 0, 0)
233 constr:setEnableCollision(true)
234 end
235 local springForce = 7500
236 local springDamping = 1500
237 constr:setRotationLimitSpring(springForce, springDamping, springForce, springDamping, springForce, springDamping)
238 constr:setTranslationLimitSpring(springForce, springDamping, springForce, springDamping, springForce, springDamping)
239
240 return constr:finalize(), jointTransform
241end

onDelete

Description
Definition
onDelete()
Code
99function LogGrab:onDelete()
100 if self.isServer then
101 local spec = self.spec_logGrab
102
103 if spec.triggerNode ~= nil then
104 removeTrigger(spec.triggerNode)
105 end
106 end
107end

onLoad

Description
Definition
onLoad()
Code
46function LogGrab:onLoad(savegame)
47 local spec = self.spec_logGrab
48
49 if self.isServer then
50 spec.grabs = {}
51
52 local i = 0
53 while true do
54 local baseKey = string.format("%s.grab(%d)", "vehicle.logGrab", i)
55 if not hasXMLProperty(self.xmlFile, baseKey) then
56 break
57 end
58
59 local entry = {}
60 entry.componentJoint = getXMLInt(self.xmlFile, baseKey.."#componentJoint")
61 entry.dampingFactor = getXMLFloat(self.xmlFile, baseKey.."#dampingFactor") or 20
62 entry.axis = getXMLInt(self.xmlFile, baseKey.."#axis") or 1
63 entry.direction = {0, 0, 0}
64 entry.direction[entry.axis] = 1
65
66 local componentJoint = self.componentJoints[entry.componentJoint]
67 if componentJoint ~= nil then
68 entry.startRotDifference = {localDirectionToLocal(self.components[componentJoint.componentIndices[2]].node, componentJoint.jointNode, unpack(entry.direction))}
69 end
70
71 entry.rotationOffsetThreshold = Utils.getNoNilRad(getXMLFloat(self.xmlFile, baseKey.."#rotationOffsetThreshold"), math.rad(10))
72 entry.rotationOffsetTime = Utils.getNoNil(getXMLFloat(self.xmlFile, baseKey.."#rotationOffsetTime"), 1000)
73 entry.rotationOffsetTimer = 0
74 entry.currentOffset = 0
75
76 table.insert(spec.grabs, entry)
77 i = i + 1
78 end
79
80 spec.jointNode = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.logGrab#jointNode"), self.i3dMappings)
81 spec.jointRoot = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.logGrab#jointRoot"), self.i3dMappings)
82
83 spec.lockAllAxis = Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.logGrab#lockAllAxis"), false)
84
85 spec.triggerNode = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.logGrab.trigger#node"), self.i3dMappings)
86 if spec.triggerNode ~= nil then
87 addTrigger(spec.triggerNode, "logGrabTriggerCallback", self)
88 end
89
90 spec.pendingDynamicMountShapes = {}
91 spec.dynamicMountedShapes = {}
92
93 spec.jointLimitsOpen = false
94 end
95end

onUpdateTick

Description
Definition
onUpdateTick()
Code
111function LogGrab:onUpdateTick(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
112 if self.isServer then
113 local spec = self.spec_logGrab
114
115 local isGrabClosed = true
116 for _, grab in ipairs(spec.grabs) do
117 if not self:updateLogGrabState(grab, dt) then
118 isGrabClosed = false
119 end
120 end
121
122 for shape,_ in pairs(spec.pendingDynamicMountShapes) do
123 if not entityExists(shape) then
124 spec.pendingDynamicMountShapes[shape] = nil
125 end
126 end
127
128 if isGrabClosed then
129 for shape,_ in pairs(spec.pendingDynamicMountShapes) do
130 if spec.dynamicMountedShapes[shape] == nil then
131 local jointIndex, jointTransform = self:mountSplitShape(shape)
132 if jointIndex ~= nil then
133 spec.dynamicMountedShapes[shape] = {jointIndex=jointIndex, jointTransform=jointTransform}
134 spec.pendingDynamicMountShapes[shape] = nil
135 end
136 end
137 end
138
139 if not spec.jointLimitsOpen and next(spec.dynamicMountedShapes) ~= nil then
140 spec.jointLimitsOpen = true
141
142 for _, grab in ipairs(spec.grabs) do
143 local componentJoint = self.componentJoints[grab.componentJoint]
144 if componentJoint ~= nil then
145 for i=1, 3 do
146 setJointRotationLimitSpring(componentJoint.jointIndex, i-1, componentJoint.rotLimitSpring[i], componentJoint.rotLimitDamping[i]*grab.dampingFactor)
147 end
148 end
149 end
150 end
151 else
152 for shapeId, shapeData in pairs(spec.dynamicMountedShapes) do
153 self:unmountSplitShape(shapeId, shapeData.jointIndex, shapeData.jointTransform, false)
154 end
155
156 if spec.jointLimitsOpen then
157 spec.jointLimitsOpen = false
158
159 for _, grab in ipairs(spec.grabs) do
160 local componentJoint = self.componentJoints[grab.componentJoint]
161 if componentJoint ~= nil then
162 for i=1, 3 do
163 setJointRotationLimitSpring(componentJoint.jointIndex, i-1, componentJoint.rotLimitSpring[i], componentJoint.rotLimitDamping[i])
164 end
165 end
166 end
167 end
168 end
169 end
170end

prerequisitesPresent

Description
Definition
prerequisitesPresent()
Code
15function LogGrab.prerequisitesPresent(specializations)
16 return true
17end

registerEventListeners

Description
Definition
registerEventListeners()
Code
38function LogGrab.registerEventListeners(vehicleType)
39 SpecializationUtil.registerEventListener(vehicleType, "onLoad", LogGrab)
40 SpecializationUtil.registerEventListener(vehicleType, "onDelete", LogGrab)
41 SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", LogGrab)
42end

registerFunctions

Description
Definition
registerFunctions()
Code
21function LogGrab.registerFunctions(vehicleType)
22 SpecializationUtil.registerFunction(vehicleType, "logGrabTriggerCallback", LogGrab.logGrabTriggerCallback)
23
24 SpecializationUtil.registerFunction(vehicleType, "updateLogGrabState", LogGrab.updateLogGrabState)
25 SpecializationUtil.registerFunction(vehicleType, "mountSplitShape", LogGrab.mountSplitShape)
26 SpecializationUtil.registerFunction(vehicleType, "unmountSplitShape", LogGrab.unmountSplitShape)
27end

registerOverwrittenFunctions

Description
Definition
registerOverwrittenFunctions()
Code
31function LogGrab.registerOverwrittenFunctions(vehicleType)
32 SpecializationUtil.registerOverwrittenFunction(vehicleType, "addNodeObjectMapping", LogGrab.addNodeObjectMapping)
33 SpecializationUtil.registerOverwrittenFunction(vehicleType, "removeNodeObjectMapping", LogGrab.removeNodeObjectMapping)
34end

removeNodeObjectMapping

Description
Definition
removeNodeObjectMapping()
Code
295function LogGrab:removeNodeObjectMapping(superFunc, list)
296 superFunc(self, list)
297
298 local spec = self.spec_logGrab
299 if spec.logGrabTrigger ~= nil and spec.logGrabTrigger.triggerNode ~= nil then
300 list[spec.logGrabTrigger.triggerNode] = nil
301 end
302end

unmountSplitShape

Description
Definition
unmountSplitShape()
Code
245function LogGrab:unmountSplitShape(shapeId, jointIndex, jointTransform, isDeleting)
246 removeJoint(jointIndex)
247 delete(jointTransform)
248
249 local spec = self.spec_logGrab
250
251 spec.dynamicMountedShapes[shapeId] = nil
252 if isDeleting ~= nil and isDeleting then
253 spec.pendingDynamicMountShapes[shapeId] = nil
254 else
255 spec.pendingDynamicMountShapes[shapeId] = true
256 end
257end

updateDebugValues

Description
Definition
updateDebugValues()
Code
306function LogGrab:updateDebugValues(values)
307 local spec = self.spec_logGrab
308
309 for i, grab in ipairs(spec.grabs) do
310 table.insert(values, {name=string.format("grab (%d):", i), value=string.format("current: %.2fdeg / threshold: %.2fdeg (timer: %d)", math.deg(math.abs(grab.currentOffset)), math.deg(grab.rotationOffsetThreshold), grab.rotationOffsetTimer)})
311 end
312
313 for shapeId, _ in pairs(spec.dynamicMountedShapes) do
314 table.insert(values, {name="mounted: ", value=tostring(getName(shapeId))})
315 end
316
317 for shapeId, _ in pairs(spec.pendingDynamicMountShapes) do
318 table.insert(values, {name="pending: ", value=tostring(getName(shapeId))})
319 end
320end

updateLogGrabState

Description
Definition
updateLogGrabState()
Code
174function LogGrab:updateLogGrabState(grab, dt)
175 local componentJoint = self.componentJoints[grab.componentJoint]
176 if componentJoint ~= nil then
177 local start = grab.startRotDifference
178 local dirX, dirY, dirZ = localDirectionToLocal(self.components[componentJoint.componentIndices[2]].node, componentJoint.jointNode, unpack(grab.direction))
179
180 local currentOffset = 0
181 if grab.axis == 1 then
182 currentOffset = start[1]-dirX
183 elseif grab.axis == 2 then
184 currentOffset = start[2]-dirY
185 elseif grab.axis == 3 then
186 currentOffset = start[3]-dirZ
187 end
188
189 if math.abs(currentOffset) > grab.rotationOffsetThreshold then
190 if grab.rotationOffsetTimer > grab.rotationOffsetTime then
191 return true
192 else
193 grab.rotationOffsetTimer = grab.rotationOffsetTimer + dt
194 end
195 elseif grab.rotationOffsetTimer > 0 then
196 local x, y, z = getRotation(componentJoint.jointNode)
197 local rotSum = x + y + z
198 -- only unmount if the rotation of the componentJoint has changed -> if user opens the grab
199 if grab.lastRotation ~= nil and rotSum ~= grab.lastRotation then
200 grab.rotationOffsetTimer = 0
201 grab.lastRotation = nil
202 else
203 grab.lastRotation = rotSum
204 return true
205 end
206 end
207
208 grab.currentOffset = currentOffset
209 end
210
211 return false
212end