LUADOC - Farming Simulator 22

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
312function LogGrab:addNodeObjectMapping(superFunc, list)
313 superFunc(self, list)
314
315 local spec = self.spec_logGrab
316 if spec.logGrabTrigger ~= nil and spec.logGrabTrigger.triggerNode ~= nil then
317 list[spec.logGrabTrigger.triggerNode] = self
318 end
319end

initSpecialization

Description
Definition
initSpecialization()
Code
21function LogGrab.initSpecialization()
22 local schema = Vehicle.xmlSchema
23 schema:setXMLSpecializationType("LogGrab")
24
25 schema:register(XMLValueType.INT, "vehicle.logGrab.grab(?)#componentJoint", "Component joint index")
26 schema:register(XMLValueType.FLOAT, "vehicle.logGrab.grab(?)#dampingFactor", "Damping factor", 20)
27 schema:register(XMLValueType.INT, "vehicle.logGrab.grab(?)#axis", "Grab axis", 1)
28 schema:register(XMLValueType.ANGLE, "vehicle.logGrab.grab(?)#rotationOffsetThreshold", "Rotation offset threshold", 10)
29 schema:register(XMLValueType.FLOAT, "vehicle.logGrab.grab(?)#rotationOffsetTime", "Rotation offset time until mount", 1000)
30
31 schema:register(XMLValueType.NODE_INDEX, "vehicle.logGrab#jointNode", "Joint node")
32 schema:register(XMLValueType.NODE_INDEX, "vehicle.logGrab#jointRoot", "Joint root node")
33 schema:register(XMLValueType.BOOL, "vehicle.logGrab#lockAllAxis", "Lock all axis", false)
34 schema:register(XMLValueType.NODE_INDEX, "vehicle.logGrab.trigger#node", "Trigger node")
35
36 schema:setXMLSpecializationType()
37end

logGrabTriggerCallback

Description
Definition
logGrabTriggerCallback()
Code
289function LogGrab:logGrabTriggerCallback(triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId)
290 local spec = self.spec_logGrab
291
292 if onEnter then
293 if getSplitType(otherActorId) ~= 0 then
294 local rigidBodyType = getRigidBodyType(otherActorId)
295 if (rigidBodyType == RigidBodyType.DYNAMIC or rigidBodyType == RigidBodyType.KINEMATIC) and spec.pendingDynamicMountShapes[otherActorId] == nil then
296 spec.pendingDynamicMountShapes[otherActorId] = true
297 end
298 end
299 elseif onLeave then
300 if getSplitType(otherActorId) ~= 0 then
301 if spec.pendingDynamicMountShapes[otherActorId] ~= nil then
302 spec.pendingDynamicMountShapes[otherActorId] = nil
303 elseif spec.dynamicMountedShapes[otherActorId] ~= nil then
304 self:unmountSplitShape(otherActorId, spec.dynamicMountedShapes[otherActorId].jointIndex, spec.dynamicMountedShapes[otherActorId].jointTransform, true)
305 end
306 end
307 end
308end

mountSplitShape

Description
Definition
mountSplitShape()
Code
244function LogGrab:mountSplitShape(shapeId)
245 local spec = self.spec_logGrab
246
247 local constr = JointConstructor.new()
248 constr:setActors(spec.jointRoot, shapeId)
249
250 local jointTransform = createTransformGroup("dynamicMountJoint")
251 link(spec.jointNode, jointTransform)
252
253 constr:setJointTransforms(jointTransform, jointTransform)
254
255 constr:setRotationLimit(0, 0, 0)
256 constr:setRotationLimit(1, 0, 0)
257 constr:setRotationLimit(2, 0, 0)
258 if not spec.lockAllAxis then
259 constr:setTranslationLimit(1, false, 0, 0)
260 constr:setTranslationLimit(2, false, 0, 0)
261 constr:setEnableCollision(true)
262 end
263 local springForce = 7500
264 local springDamping = 1500
265 constr:setRotationLimitSpring(springForce, springDamping, springForce, springDamping, springForce, springDamping)
266 constr:setTranslationLimitSpring(springForce, springDamping, springForce, springDamping, springForce, springDamping)
267
268 return constr:finalize(), jointTransform
269end

onDelete

Description
Definition
onDelete()
Code
124function LogGrab:onDelete()
125 local spec = self.spec_logGrab
126
127 if spec.triggerNode ~= nil then
128 removeTrigger(spec.triggerNode)
129 end
130end

onLoad

Description
Definition
onLoad()
Code
66function LogGrab:onLoad(savegame)
67 local spec = self.spec_logGrab
68
69 if self.isServer then
70 spec.grabs = {}
71
72 local i = 0
73 while true do
74 local baseKey = string.format("vehicle.logGrab.grab(%d)", i)
75 if not self.xmlFile:hasProperty(baseKey) then
76 break
77 end
78
79 local entry = {}
80 entry.componentJoint = self.xmlFile:getValue(baseKey.."#componentJoint")
81 entry.dampingFactor = self.xmlFile:getValue(baseKey.."#dampingFactor", 20)
82 entry.axis = self.xmlFile:getValue(baseKey.."#axis", 1)
83 entry.direction = {0, 0, 0}
84 entry.direction[entry.axis] = 1
85
86 local componentJoint = self.componentJoints[entry.componentJoint]
87 if componentJoint ~= nil then
88 entry.startRotDifference = {localDirectionToLocal(self.components[componentJoint.componentIndices[2]].node, componentJoint.jointNode, unpack(entry.direction))}
89 end
90
91 entry.rotationOffsetThreshold = self.xmlFile:getValue(baseKey.."#rotationOffsetThreshold", 10)
92 entry.rotationOffsetTime = self.xmlFile:getValue(baseKey.."#rotationOffsetTime", 1000)
93 entry.rotationOffsetTimer = 0
94 entry.rotationChangedTimer = 0
95 entry.currentOffset = 0
96
97 table.insert(spec.grabs, entry)
98 i = i + 1
99 end
100
101 spec.jointNode = self.xmlFile:getValue("vehicle.logGrab#jointNode", nil, self.components, self.i3dMappings)
102 spec.jointRoot = self.xmlFile:getValue("vehicle.logGrab#jointRoot", nil, self.components, self.i3dMappings)
103
104 spec.lockAllAxis = self.xmlFile:getValue("vehicle.logGrab#lockAllAxis", false)
105
106 spec.triggerNode = self.xmlFile:getValue("vehicle.logGrab.trigger#node", nil, self.components, self.i3dMappings)
107 if spec.triggerNode ~= nil then
108 addTrigger(spec.triggerNode, "logGrabTriggerCallback", self)
109 end
110
111 spec.pendingDynamicMountShapes = {}
112 spec.dynamicMountedShapes = {}
113
114 spec.jointLimitsOpen = false
115 end
116
117 if not self.isServer then
118 SpecializationUtil.removeEventListener(self, "onUpdateTick", LogGrab)
119 end
120end

onUpdateTick

Description
Definition
onUpdateTick()
Code
134function LogGrab:onUpdateTick(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
135 local spec = self.spec_logGrab
136
137 local isGrabClosed = true
138 for _, grab in ipairs(spec.grabs) do
139 if not self:updateLogGrabState(grab, dt) then
140 isGrabClosed = false
141 end
142 end
143
144 for shape,_ in pairs(spec.pendingDynamicMountShapes) do
145 if not entityExists(shape) then
146 spec.pendingDynamicMountShapes[shape] = nil
147 end
148 end
149
150 if isGrabClosed then
151 for shape,_ in pairs(spec.pendingDynamicMountShapes) do
152 if spec.dynamicMountedShapes[shape] == nil then
153 local jointIndex, jointTransform = self:mountSplitShape(shape)
154 if jointIndex ~= nil then
155 spec.dynamicMountedShapes[shape] = {jointIndex=jointIndex, jointTransform=jointTransform}
156 spec.pendingDynamicMountShapes[shape] = nil
157 end
158 end
159 end
160
161 if not spec.jointLimitsOpen and next(spec.dynamicMountedShapes) ~= nil then
162 spec.jointLimitsOpen = true
163
164 for _, grab in ipairs(spec.grabs) do
165 local componentJoint = self.componentJoints[grab.componentJoint]
166 if componentJoint ~= nil then
167 for i=1, 3 do
168 setJointRotationLimitSpring(componentJoint.jointIndex, i-1, componentJoint.rotLimitSpring[i], componentJoint.rotLimitDamping[i]*grab.dampingFactor)
169 end
170 end
171 end
172 end
173 else
174 for shapeId, shapeData in pairs(spec.dynamicMountedShapes) do
175 self:unmountSplitShape(shapeId, shapeData.jointIndex, shapeData.jointTransform, false)
176 end
177
178 if spec.jointLimitsOpen then
179 spec.jointLimitsOpen = false
180
181 for _, grab in ipairs(spec.grabs) do
182 local componentJoint = self.componentJoints[grab.componentJoint]
183 if componentJoint ~= nil then
184 for i=1, 3 do
185 setJointRotationLimitSpring(componentJoint.jointIndex, i-1, componentJoint.rotLimitSpring[i], componentJoint.rotLimitDamping[i])
186 end
187 end
188 end
189 end
190 end
191end

prerequisitesPresent

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

registerEventListeners

Description
Definition
registerEventListeners()
Code
58function LogGrab.registerEventListeners(vehicleType)
59 SpecializationUtil.registerEventListener(vehicleType, "onLoad", LogGrab)
60 SpecializationUtil.registerEventListener(vehicleType, "onDelete", LogGrab)
61 SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", LogGrab)
62end

registerFunctions

Description
Definition
registerFunctions()
Code
41function LogGrab.registerFunctions(vehicleType)
42 SpecializationUtil.registerFunction(vehicleType, "logGrabTriggerCallback", LogGrab.logGrabTriggerCallback)
43
44 SpecializationUtil.registerFunction(vehicleType, "updateLogGrabState", LogGrab.updateLogGrabState)
45 SpecializationUtil.registerFunction(vehicleType, "mountSplitShape", LogGrab.mountSplitShape)
46 SpecializationUtil.registerFunction(vehicleType, "unmountSplitShape", LogGrab.unmountSplitShape)
47end

registerOverwrittenFunctions

Description
Definition
registerOverwrittenFunctions()
Code
51function LogGrab.registerOverwrittenFunctions(vehicleType)
52 SpecializationUtil.registerOverwrittenFunction(vehicleType, "addNodeObjectMapping", LogGrab.addNodeObjectMapping)
53 SpecializationUtil.registerOverwrittenFunction(vehicleType, "removeNodeObjectMapping", LogGrab.removeNodeObjectMapping)
54end

removeNodeObjectMapping

Description
Definition
removeNodeObjectMapping()
Code
323function LogGrab:removeNodeObjectMapping(superFunc, list)
324 superFunc(self, list)
325
326 local spec = self.spec_logGrab
327 if spec.logGrabTrigger ~= nil and spec.logGrabTrigger.triggerNode ~= nil then
328 list[spec.logGrabTrigger.triggerNode] = nil
329 end
330end

unmountSplitShape

Description
Definition
unmountSplitShape()
Code
273function LogGrab:unmountSplitShape(shapeId, jointIndex, jointTransform, isDeleting)
274 removeJoint(jointIndex)
275 delete(jointTransform)
276
277 local spec = self.spec_logGrab
278
279 spec.dynamicMountedShapes[shapeId] = nil
280 if isDeleting ~= nil and isDeleting then
281 spec.pendingDynamicMountShapes[shapeId] = nil
282 else
283 spec.pendingDynamicMountShapes[shapeId] = true
284 end
285end

updateDebugValues

Description
Definition
updateDebugValues()
Code
334function LogGrab:updateDebugValues(values)
335 local spec = self.spec_logGrab
336
337 if self.isServer then
338 for i, grab in ipairs(spec.grabs) do
339 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)})
340 end
341
342 for shapeId, _ in pairs(spec.dynamicMountedShapes) do
343 if entityExists(shapeId) then
344 table.insert(values, {name="mounted: ", value=tostring(getName(shapeId))})
345 end
346 end
347
348 for shapeId, _ in pairs(spec.pendingDynamicMountShapes) do
349 if entityExists(shapeId) then
350 table.insert(values, {name="pending: ", value=tostring(getName(shapeId))})
351 end
352 end
353 end
354end

updateLogGrabState

Description
Definition
updateLogGrabState()
Code
195function LogGrab:updateLogGrabState(grab, dt)
196 local componentJoint = self.componentJoints[grab.componentJoint]
197 if componentJoint ~= nil then
198 local start = grab.startRotDifference
199 local dirX, dirY, dirZ = localDirectionToLocal(self.components[componentJoint.componentIndices[2]].node, componentJoint.jointNode, unpack(grab.direction))
200
201 local currentOffset = 0
202 if grab.axis == 1 then
203 currentOffset = start[1]-dirX
204 elseif grab.axis == 2 then
205 currentOffset = start[2]-dirY
206 elseif grab.axis == 3 then
207 currentOffset = start[3]-dirZ
208 end
209
210 if math.abs(currentOffset) > grab.rotationOffsetThreshold then
211 if grab.rotationOffsetTimer > grab.rotationOffsetTime then
212 return true
213 else
214 grab.rotationOffsetTimer = grab.rotationOffsetTimer + dt
215 end
216 elseif grab.rotationOffsetTimer > 0 then
217 local x, y, z = getRotation(componentJoint.jointNode)
218 local rotSum = x + y + z
219 -- only unmount if the rotation of the componentJoint has changed -> if user opens the grab
220 if grab.lastRotation ~= nil and rotSum ~= grab.lastRotation then
221 grab.rotationOffsetTimer = 0
222 grab.rotationChangedTimer = 750
223 grab.lastRotation = nil
224 else
225 grab.rotationChangedTimer = math.max(grab.rotationChangedTimer - dt)
226 if grab.rotationChangedTimer <= 0 then
227 grab.lastRotation = rotSum
228 return true
229 else
230 grab.rotationOffsetTimer = 0
231 grab.lastRotation = nil
232 end
233 end
234 end
235
236 grab.currentOffset = currentOffset
237 end
238
239 return false
240end