LUADOC - Farming Simulator 22

PlayerModel

Description
A player model with sounds and animations
Functions

load

Description
Load player model, async.
Definition
load(string xmlFilename, bool isRealPlayer, bool isOwner, bool isAnimated, function asyncCallbackFunction, table asyncCallbackObject, table asyncCallbackArguments)
Arguments
stringxmlFilenameXML filename
boolisRealPlayerfalse if player is in a vehicle
boolisOwnertrue if this is a client that owns the player
boolisAnimatedtrue if animations should be loaded
functionasyncCallbackFunctionfunction to call after loading success of failure. Arguments: object, result true/false, arguments
tableasyncCallbackObjectcall receiver
tableasyncCallbackArgumentsArguments passed to the callback
Code
173function PlayerModel:load(xmlFilename, isRealPlayer, isOwner, isAnimated, asyncCallbackFunction, asyncCallbackObject, asyncCallbackArguments)
174 self.xmlFilename = xmlFilename
175 self.customEnvironment, self.baseDirectory = Utils.getModNameAndBaseDirectory(xmlFilename)
176
177 local xmlFile = loadXMLFile("playerXML", xmlFilename)
178 if xmlFile == 0 then
179 asyncCallbackFunction(asyncCallbackObject, false, asyncCallbackArguments)
180 return
181 end
182
183 -- Find the filename of the player
184 local filename = getXMLString(xmlFile, "player.filename")
185 self.filename = Utils.getFilename(filename, self.baseDirectory)
186
187 self.isRealPlayer = isRealPlayer
188
189 -- Load the player i3d
190 self.asyncLoadCallbackFunction, self.asyncLoadCallbackObject, self.asyncLoadCallbackArguments = asyncCallbackFunction, asyncCallbackObject, asyncCallbackArguments
191 self.sharedLoadRequestId = g_i3DManager:loadSharedI3DFileAsync(self.filename, false, false, self.loadFileFinished, self, {isRealPlayer, isOwner, isAnimated})
192
193 delete(xmlFile)
194end

loadFileFinished

Description
Async result of i3d loading
Definition
loadFileFinished()
Code
198function PlayerModel:loadFileFinished(rootNode, failedReason, arguments)
199
200 if failedReason == LoadI3DFailedReason.FILE_NOT_FOUND then
201 Logging.error("Player model file '%s' does not exist!", self.filename)
202 return self.asyncLoadCallbackFunction(self.asyncLoadCallbackObject, false, self.asyncLoadCallbackArguments)
203 end
204
205 if failedReason == LoadI3DFailedReason.UNKNOWN or rootNode == nil or rootNode == 0 then
206 Logging.error("Failed to load player model %s", self.filename, failedReason)
207 return self.asyncLoadCallbackFunction(self.asyncLoadCallbackObject, false, self.asyncLoadCallbackArguments)
208 end
209
210 local xmlFile = loadXMLFile("playerXML", self.xmlFilename)
211 if xmlFile == 0 then
212 return self.asyncLoadCallbackFunction(self.asyncLoadCallbackObject, false, self.asyncLoadCallbackArguments)
213 end
214
215 local isRealPlayer = arguments[1]
216 local isOwner = arguments[2]
217 local isAnimated = arguments[3]
218
219 self.rootNode = rootNode
220
221 -- Find nodes references in the XML first, before re-linking other nodes that change the hierarchy
222 if isRealPlayer then
223 local cNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.camera#index"))
224 if cNode == nil then
225 Logging.devError("Error: Failed to find player camera position in '%s'", self.filename)
226 end
227
228 local x, y, z = localToLocal(cNode, rootNode, 0, 0, 0)
229
230 local target = createTransformGroup("1p_camera_target")
231 link(rootNode, target)
232 setTranslation(target, x, y, z)
233
234 self.firstPersonCameraTarget = target
235 end
236
237 if isRealPlayer then
238 self.animRootThirdPerson = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.character.thirdPerson#animRootNode"))
239 if self.animRootThirdPerson == nil then
240 Logging.devError("Error: Failed to find animation root node in '%s'", self.filename)
241 return self.asyncLoadCallbackFunction(self.asyncLoadCallbackObject, false, self.asyncLoadCallbackArguments)
242 end
243
244 -- Capsule information
245 self.capsuleHeight = getXMLFloat(xmlFile, "player.character#physicsCapsuleHeight")
246 self.capsuleRadius = getXMLFloat(xmlFile, "player.character#physicsCapsuleRadius")
247 self.capsuleTotalHeight = self.capsuleHeight + self.capsuleRadius * 2
248 end
249
250 -- Avator customization
251 self.style = PlayerStyle.new()
252 -- self.style:loadConfigurationXML(self.xmlFilename)
253
254 self.skeleton = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.character.thirdPerson#skeleton"))
255 if self.skeleton == nil then
256 Logging.devError("Error: Failed to find skeleton root node in '%s'", self.filename)
257 end
258
259 self.mesh = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.character.thirdPerson#mesh"))
260 if self.mesh == nil then
261 Logging.devError("Error: Failed to find player mesh in '%s'", self.filename)
262 end
263
264 -- Used for linking elements (handtools, lights)
265 self.thirdPersonSpineNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.character.thirdPerson#spine"))
266 self.thirdPersonSuspensionNode = Utils.getNoNil(I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.character.thirdPerson#suspension")), self.thirdPersonSpineNode)
267 self.thirdPersonRightHandNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.character.thirdPerson#rightHandNode"))
268 self.thirdPersonLeftHandNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.character.thirdPerson#leftHandNode"))
269 self.thirdPersonHeadNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.character.thirdPerson#headNode"))
270
271 -- Torchlight
272 self.lightNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.light#index"))
273 if self.lightNode ~= nil then
274 setVisibility(self.lightNode, false)
275 end
276
277 -- Relink only after the lights and cameras are loaded: indexing changes
278 if self.mesh ~= nil then
279 -- link(self.rootNode, self.mesh)
280 setClipDistance(self.mesh, 200)
281 end
282
283 local pickUpKinematicHelperNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.pickUpKinematicHelper#index"))
284 if pickUpKinematicHelperNode ~= nil then
285 if getRigidBodyType(pickUpKinematicHelperNode) == RigidBodyType.KINEMATIC then
286 self.pickUpKinematicHelperNode = pickUpKinematicHelperNode
287 self.pickUpKinematicHelperNodeChild = createTransformGroup("pickUpKinematicHelperNodeChild")
288 link(self.pickUpKinematicHelperNode, self.pickUpKinematicHelperNodeChild)
289
290 addToPhysics(self.pickUpKinematicHelperNode)
291 else
292 Logging.xmlWarning(xmlFile, "Given pickUpKinematicHelper '%s' is not a kinematic object", getName(pickUpKinematicHelperNode))
293 end
294 end
295
296 -- IK Chains
297 self:loadIKChains(xmlFile, rootNode, isRealPlayer)
298
299 if isAnimated then
300 if self.skeleton ~= nil and getNumOfChildren(self.skeleton) > 0 then
301 local animNode = g_animCache:getNode(AnimationCache.CHARACTER)
302 cloneAnimCharacterSet(animNode, getParent(self.skeleton))
303 local animCharsetId = getAnimCharacterSet(getChildAt(self.skeleton, 0))
304 self.animationInformation.player = createConditionalAnimation()
305
306 for key, parameter in pairs(self.animationInformation.parameters) do
307 conditionalAnimationRegisterParameter(self.animationInformation.player, parameter.id, parameter.type, key)
308 end
309 initConditionalAnimation(self.animationInformation.player, animCharsetId, self.xmlFilename, "player.conditionalAnimation")
310 setConditionalAnimationSpecificParameterIds(self.animationInformation.player, self.animationInformation.parameters.absForwardVelocity.id, self.animationInformation.parameters.yawVelocity.id)
311 end
312 end
313
314 if isRealPlayer then
315 self.skeletonRootNode = createTransformGroup("player_skeletonRootNode")
316
317 link(getRootNode(), self.rootNode)
318 link(self.rootNode, self.skeletonRootNode)
319
320 if self.animRootThirdPerson ~= nil then
321 link(self.skeletonRootNode, self.animRootThirdPerson)
322 if self.skeleton ~= nil then
323 link(self.animRootThirdPerson, self.skeleton)
324 end
325 end
326
327 self.leftArmToolNode = createTransformGroup("leftArmToolNode")
328 self.rightArmToolNode = createTransformGroup("rightArmToolNode")
329
330 if isOwner then
331 local toolRotation = string.getVectorN(Utils.getNoNil(getXMLString(xmlFile, "player.character.toolNode#firstPersonRotation"), "0 0 0"), 3)
332 local rotX, rotY, rotZ = unpack(toolRotation)
333 setRotation(self.rightArmToolNode, math.rad(rotX), math.rad(rotY), math.rad(rotZ))
334 local toolTranslate = string.getVectorN(Utils.getNoNil(getXMLString(xmlFile, "player.character.toolNode#firstPersonTranslation"), "0 0 0"), 3)
335 local transX, transY, transZ = unpack(toolTranslate)
336 setTranslation(self.rightArmToolNode, transX, transY, transZ)
337 else
338 -- right hand tool
339 local toolRotationR = string.getVectorN(Utils.getNoNil(getXMLString(xmlFile, "player.character.toolNode#thirdPersonRightNodeRotation"), "0 0 0"), 3)
340 local rotRX, rotRY, rotRZ = unpack(toolRotationR)
341 setRotation(self.rightArmToolNode, math.rad(rotRX), math.rad(rotRY), math.rad(rotRZ))
342 local toolTranslateR = string.getVectorN(Utils.getNoNil(getXMLString(xmlFile, "player.character.toolNode#thirdPersonRightNodeTranslation"), "0 0 0"), 3)
343 local transRX, transRY, transRZ = unpack(toolTranslateR)
344 setTranslation(self.rightArmToolNode, transRX, transRY, transRZ)
345 link(self.thirdPersonRightHandNode, self.rightArmToolNode)
346
347 -- left hand tool
348 local toolRotationL = string.getVectorN(Utils.getNoNil(getXMLString(xmlFile, "player.character.toolNode#thirdPersonLeftNodeRotation"), "0 0 0"), 3)
349 local rotLX, rotLY, rotLZ = unpack(toolRotationL)
350 setRotation(self.leftArmToolNode, math.rad(rotLX), math.rad(rotLY), math.rad(rotLZ))
351 local toolTranslateL = string.getVectorN(Utils.getNoNil(getXMLString(xmlFile, "player.character.toolNode#thirdPersonLeftNodeTranslation"), "0 0 0"), 3)
352 local transLX, transLY, transLZ = unpack(toolTranslateL)
353 setTranslation(self.leftArmToolNode, transLX, transLY, transLZ)
354 link(self.thirdPersonLeftHandNode, self.leftArmToolNode)
355
356 -- light: attached to the head
357 link(self.thirdPersonHeadNode, self.lightNode)
358 local lightRotation = string.getVectorN(Utils.getNoNil(getXMLString(xmlFile, "player.light#thirdPersonRotation"), "0 0 0"), 3)
359 local lightRotX, lightRotY, lightRotZ = unpack(lightRotation)
360 local lightTranslate = string.getVectorN(Utils.getNoNil(getXMLString(xmlFile, "player.light#thirdPersonTranslation"), "0 0 0"), 3)
361 local lightTransX, lightTransY, lightTransZ = unpack(lightTranslate)
362 setRotation(self.lightNode, math.rad(lightRotX), math.rad(lightRotY), math.rad(lightRotZ))
363 setTranslation(self.lightNode, lightTransX, lightTransY, lightTransZ)
364 end
365
366 -- Fx
367 self.particleSystemsInformation.swimNode = createTransformGroup("swimFXNode")
368 link(getRootNode(), self.particleSystemsInformation.swimNode)
369 self.particleSystemsInformation.plungeNode = createTransformGroup("plungeFXNode")
370 link(getRootNode(), self.particleSystemsInformation.plungeNode)
371
372 ParticleUtil.loadParticleSystem(xmlFile, self.particleSystemsInformation.systems.swim, "player.particleSystems.swim", self.particleSystemsInformation.swimNode, false, nil, self.baseDirectory)
373 ParticleUtil.loadParticleSystem(xmlFile, self.particleSystemsInformation.systems.plunge, "player.particleSystems.plunge", self.particleSystemsInformation.plungeNode, false, nil, self.baseDirectory)
374 else
375 -- Will be re-linked in linkTo:
376 if not isAnimated then
377 local linkNode = createTransformGroup("characterLinkNode")
378 link(self.rootNode, linkNode)
379 link(linkNode, self.skeleton)
380
381 local x, y, z = localToLocal(self.thirdPersonSpineNode, self.skeleton, 0, 0, 0)
382 setTranslation(linkNode, -x, -y, -z)
383 else
384 link(self.rootNode, self.skeleton)
385 end
386
387 if self.pickUpKinematicHelperNode ~= nil then
388 delete(self.pickUpKinematicHelperNode)
389 self.pickUpKinematicHelperNode = nil
390 end
391 if self.lightNode ~= nil then
392 delete(self.lightNode)
393 self.lightNode = nil
394 end
395 -- if self.cameraNode ~= nil then
396 -- delete(self.cameraNode)
397 -- self.cameraNode = nil
398 -- end
399
400 -- self.visualInformation:applySelection()
401 -- self.visualInformation:setVisibility(true)
402 end
403
404 -- Sound
405 if isRealPlayer and Platform.hasPlayer then
406 self:loadSounds(xmlFile, isOwner)
407 end
408
409 delete(xmlFile)
410
411 self.isLoaded = true
412
413 return self.asyncLoadCallbackFunction(self.asyncLoadCallbackObject, true, self.asyncLoadCallbackArguments)
414end

new

Description
Creating manager
Definition
new()
Return Values
tableinstanceinstance of object
Code
16function PlayerModel.new(customMt)
17 local self = setmetatable({}, customMt or PlayerModel_mt)
18
19 self.isLoaded = false
20 self.sharedLoadRequestIds = {}
21 self.modelParts = {}
22
23 self.capsuleHeight = 0.8
24 self.capsuleRadius = 0.4
25 self.capsuleTotalHeight = self.capsuleHeight + (self.capsuleRadius * 2)
26
27 self.style = nil
28
29 self.ikChains = {}
30
31 -- SOUND
32 self.soundInformation = {
33 samples = {
34 swim = {},
35 plunge = {},
36 horseBrush = {}
37 },
38 distancePerFootstep = {
39 crouch = 0.5,
40 walk = 0.75,
41 run = 1.5
42 },
43 distanceSinceLastFootstep = 0.0
44 }
45
46 -- PARTICLES
47 self.particleSystemsInformation = {
48 systems = {
49 swim = {},
50 plunge = {}
51 },
52 swimNode = nil,
53 plungeNode = nil
54 }
55
56 -- ANIMATION
57 self.animationInformation = {}
58 self.animationInformation.player = 0
59 self.animationInformation.parameters = {
60 forwardVelocity = {id=1, value=0.0, type=1},
61 verticalVelocity = {id=2, value=0.0, type=1},
62 yawVelocity = {id=3, value=0.0, type=1},
63 absYawVelocity = {id=4, value=0.0, type=1},
64 onGround = {id=5, value=false, type=0},
65 inWater = {id=6, value=false, type=0},
66 isCrouched = {id=7, value=false, type=0},
67 absForwardVelocity = {id=8, value=0.0, type=1},
68 isCloseToGround = {id=9, value=false, type=0},
69 isUsingChainsawHorizontal = {id=10, value=false, type=0},
70 isUsingChainsawVertical = {id=11, value=false, type=0}
71 }
72
73 return self
74end

readStream

Description
Reads from network stream
Definition
readStream(integer streamId, table connection)
Arguments
integerstreamIdid of the stream to read
tableconnectionconnection information
Code
514function PlayerModel:readStream(streamId, connection)
515end

writeStream

Description
Writes in network stream
Definition
writeStream(integer streamId, table connection)
Arguments
integerstreamIdid of the stream to read
tableconnectionconnection information
Code
521function PlayerModel:writeStream(streamId, connection)
522end