Script v1_7_1_0
- AI
- Animals
- Collections
- Contracts
- Debug
- Economy
- Elements
- EnvironmentalScore
- Errors
- Events
- GUI
- Handtools
- Hud
- I3d
- Input
- Jobs
- Maps
- Materials
- Misc
- Objects
- Parameters
- Placeables
- Placement
- Player
- Shop
- Sounds
- Specialization
- Specializations
- StateMachine
- Statistics
- Tasks
- Triggers
- Utils
- Vehicles
Engine v1_7_1_0
- AI
- Animation
- Camera
- Entity
- Fillplanes
- general
- General
- I3D
- Input
- Lighting
- Math
- Network
- Node
- NoteNode
- Overlays
- Particle System
- Physics
- Rendering
- Scenegraph
- Shape
- Sound
- Spline
- String
- Terrain Detail
- Text Rendering
- Tire Track
- VoiceChat
- XML
Foundation Reference
Player
Descriptionclass.Parent
ObjectXML Configuration Parameters
player.filename | i3d file of the player |
player.camera#index | scenegraph node of the player camera |
player.light#index | scenegraph node of the light |
player.pickUpKinematicHelper#index | scenegraph node of the light |
player.character#type | "male" or "female" |
player.character#physicsCapsuleHeight | capsule height (in m) |
player.character#physicsCapsuleRadius | capsule radius (in m) |
player.character.thirdPerson#mesh | scenegraph node of the 3rd person mesh |
player.character.thirdPerson#skeleton | scenegraph node of the skeleton |
player.character.thirdPerson#animRootNode | scenegraph node of the root node |
player.character.thirdPerson#spine | scenegraph node of the spine |
player.character.thirdPerson#torso | scenegraph node of the torso |
player.character.thirdPerson#leftHandNode | scenegraph node of the left hand |
player.character.thirdPerson#rightHandNode | scenegraph node of the right hand |
player.character.firstPerson#spine | scenegraph node of the 1st person spine |
player.character.toolNode#firstPersonTranslation | translation of the tools node (in m) |
player.character.toolNode#firstPersonRotation | rotation of the tool node (in deg) |
player.character.toolNode#thirdPersonTranslation | translation of the tools node (in m) |
player.character.toolNode#thirdPersonRotation | rotation of the tool node (in deg) |
player.ikChains | see IKUtil |
player.particleSystems | see ParticleUtil |
player.sounds | see SoundManager |
player.conditionalAnimation | see c++ interface for conditionalAnimation |
Functions
- activateRideState
- calculate2DDotProductAgainstVelocity
- cameraBob
- checkObjectInRange
- consoleCommandReloadIKChains
- consoleCommandThirdPersonView
- consoleCommandToggleFlightMode
- consoleCommandToggleNoClipMode
- consoleCommandTogglePickupRaycastDebug
- consoleCommandTogglePlayerDebug
- consoleCommandToggleSuperStrongMode
- consoleCommandToggleWoodCuttingMaker
- debugDraw
- delete
- deleteStartleAnimalData
- deleteStartleAnimalSound
- draw
- drawUIInfo
- equipHandtool
- getCanEnterRideable
- getCanEnterVehicle
- getDesiredSpeed
- getEquippedHandtoolFilename
- getIsInputAllowed
- getIsRideStateAvailable
- getParentComponent
- getPositionData
- getUpdatePriority
- handToolLoaded
- hasHandtoolEquipped
- load
- loadHandTool
- lockInput
- mouseEvent
- movePlayer
- moveRootNodeToAbsolute
- moveTo
- moveToAbsolute
- moveToAbsoluteInternal
- moveToExitPoint
- new
- onEnter
- onEnterFarmhouse
- onGhostAdd
- onGhostRemove
- onInputActivateHandtool
- onInputActivateObject
- onInputCrouch
- onInputCycleHandTool
- onInputDebugFlyToggle
- onInputDebugFlyUpDown
- onInputEnter
- onInputInteract
- onInputJump
- onInputLookLeftRight
- onInputLookUpDown
- onInputMoveForward
- onInputMoveSide
- onInputRotateObjectHorizontally
- onInputRotateObjectVertically
- onInputRun
- onInputThrowObject
- onInputToggleLight
- onLeave
- onLeaveVehicle
- onPickedUpObjectJointBreak
- pickUpObject
- pickUpObjectRaycastCallback
- readStream
- readUpdateStream
- recordPositionInformation
- registerActionEvents
- removeActionEvents
- resetBrake
- resetCameraInputsInformation
- resetInputsInformation
- rotateObject
- setCustomWorkStylePreset
- setCuttingAnim
- setIKDirty
- setInputState
- setLightIsActive
- setRotation
- setThirdPersonViewActive
- setVisibility
- setWalkingLock
- testScope
- throwObject
- touchEventLookLeftRight
- touchEventLookUpDown
- unequipHandtool
- update
- updateActionEvents
- updateAnimationParameters
- updateFX
- updateInterpolation
- updateInterpolationTick
- updateKinematic
- updateNetworkMovementHistory
- updatePlayerStates
- updateRotation
- updateSound
- updateTick
- updateWaterParams
- writeStream
- writeUpdateStream
activateRideState
DescriptionDefinitionactivateRideState()Code
3205 | function Player:activateRideState() |
3206 | if not self.playerStateMachine:isActive("animalRide") then |
3207 | self.playerStateMachine:activateState("animalRide") |
3208 | end |
3209 | end |
calculate2DDotProductAgainstVelocity
DescriptionDefinitioncalculate2DDotProductAgainstVelocity()Code
2614 | function Player:calculate2DDotProductAgainstVelocity(velocity, currentSpeed, vector) |
2615 | local normalizedVelX = velocity[1] / currentSpeed |
2616 | local normalizedVelZ = velocity[3] / currentSpeed |
2617 | local vectorMagnitude = math.sqrt(vector[1] * vector[1] + vector[3] * vector[3]) |
2618 | local normalizedVectorX = vector[1] / vectorMagnitude |
2619 | local normalizedVectorZ = vector[3] / vectorMagnitude |
2620 | local dot = normalizedVelX * normalizedVectorX + normalizedVelZ * normalizedVectorZ |
2621 | |
2622 | return dot |
2623 | end |
cameraBob
DescriptionApply bobbing to the camera to imitate waves or footsteps.Definition
cameraBob()Code
2431 | function Player:cameraBob(dt) |
2432 | local amplitude = 0.0 |
2433 | local isSwimming = self.playerStateMachine:isActive("swim") |
2434 | local isWalking = self.playerStateMachine:isActive("walk") |
2435 | local isCrouching = self.playerStateMachine:isActive("crouch") |
2436 | local isRunning = self.playerStateMachine:isActive("run") |
2437 | local targetCameraOffset = 0.0 |
2438 | local dtInSec = dt * 0.001 |
2439 | |
2440 | if isSwimming then |
2441 | amplitude = 0.045 |
2442 | targetCameraOffset = self.baseInformation.waterCameraOffset |
2443 | elseif isCrouching then |
2444 | amplitude = 0.045 |
2445 | elseif isWalking or isRunning then |
2446 | amplitude = 0.025 |
2447 | end |
2448 | |
2449 | if self.baseInformation.currentWaterCameraOffset ~= targetCameraOffset then |
2450 | local deltaOffset = targetCameraOffset - self.baseInformation.currentWaterCameraOffset |
2451 | if math.abs(deltaOffset) > 0.001 then |
2452 | self.baseInformation.currentWaterCameraOffset = self.baseInformation.currentWaterCameraOffset + deltaOffset * dtInSec / 0.75 |
2453 | else |
2454 | self.baseInformation.currentWaterCameraOffset = self.baseInformation.currentWaterCameraOffset + deltaOffset |
2455 | end |
2456 | if math.abs(targetCameraOffset) > 0.001 then |
2457 | self.baseInformation.currentWaterCameraOffset = MathUtil.clamp(self.baseInformation.currentWaterCameraOffset, 0, targetCameraOffset) |
2458 | else |
2459 | self.baseInformation.currentWaterCameraOffset = math.max(self.baseInformation.currentWaterCameraOffset, 0) |
2460 | end |
2461 | end |
2462 | |
2463 | local delta |
2464 | if amplitude ~= 0.0 then |
2465 | local actualSpeed = self.motionInformation.currentCoveredGroundDistance / dtInSec |
2466 | local dtInSecClamped = math.min(dtInSec, 0.06) |
2467 | local timeOffset, amplitudeScale |
2468 | |
2469 | if isSwimming then |
2470 | timeOffset = math.min(math.max(self.motionInformation.currentCoveredGroundDistance * 1.0, 0.6 * dtInSecClamped), 3.0 * dtInSecClamped * 1.0) |
2471 | amplitudeScale = math.min(math.max(actualSpeed / 3.0, 0.5), 1.0) |
2472 | else |
2473 | timeOffset = math.min(self.motionInformation.currentCoveredGroundDistance, 3.0 * dtInSecClamped) * 3.0 |
2474 | amplitudeScale = math.min(actualSpeed / 3.0, 1.0) |
2475 | end |
2476 | |
2477 | self.baseInformation.headBobTime = self.baseInformation.headBobTime + timeOffset |
2478 | amplitudeScale = (self.baseInformation.lastCameraAmplitudeScale + amplitudeScale) * 0.5 |
2479 | delta = amplitudeScale * amplitude * math.sin(self.baseInformation.headBobTime) + self.baseInformation.currentWaterCameraOffset |
2480 | self.baseInformation.lastCameraAmplitudeScale = amplitudeScale |
2481 | else |
2482 | delta = self.baseInformation.currentWaterCameraOffset |
2483 | end |
2484 | |
2485 | return delta |
2486 | end |
checkObjectInRange
DescriptionDefinitioncheckObjectInRange()Code
2078 | function Player:checkObjectInRange() |
2079 | -- handle picking up of objects |
2080 | if self.isServer then |
2081 | if not self.isCarryingObject then |
2082 | local x,y,z = localToWorld(self.cameraNode, 0,0,1.0) |
2083 | local dx,dy,dz = localDirectionToWorld(self.cameraNode, 0,0,-1) |
2084 | self.lastFoundObject = nil |
2085 | self.lastFoundObjectHitPoint = nil |
2086 | self.lastFoundAnyObject = nil |
2087 | raycastAll(x,y,z, dx,dy,dz, "pickUpObjectRaycastCallback", Player.MAX_PICKABLE_OBJECT_DISTANCE, self) |
2088 | self.isObjectInRange = self.lastFoundObject ~= nil |
2089 | --#debug self.raycastCallbackIndex = 0 |
2090 | |
2091 | self.hudUpdater:setCurrentRaycastTarget(self.lastFoundAnyObject) |
2092 | else |
2093 | -- check if object still exists |
2094 | if self.pickedUpObject ~= nil then |
2095 | if not entityExists(self.pickedUpObject) then |
2096 | Player.PICKED_UP_OBJECTS[self.pickedUpObject] = false |
2097 | self.pickedUpObject = nil |
2098 | self.pickedUpObjectJointId = nil |
2099 | self.isCarryingObject = false |
2100 | end |
2101 | end |
2102 | end |
2103 | else |
2104 | -- Update HUD on client too |
2105 | if not self.isCarryingObject then |
2106 | local x,y,z = localToWorld(self.cameraNode, 0,0,1.0) |
2107 | local dx,dy,dz = localDirectionToWorld(self.cameraNode, 0,0,-1) |
2108 | |
2109 | self.lastFoundAnyObject = nil |
2110 | raycastAll(x,y,z, dx,dy,dz, "pickUpObjectRaycastCallback", Player.MAX_PICKABLE_OBJECT_DISTANCE, self) |
2111 | --#debug self.raycastCallbackIndex = 0 |
2112 | |
2113 | self.hudUpdater:setCurrentRaycastTarget(self.lastFoundAnyObject) |
2114 | end |
2115 | end |
2116 | end |
consoleCommandReloadIKChains
DescriptionReloads IK chains. Used when modifying IK chains in the player configuration file.Definition
consoleCommandReloadIKChains(table unusedSelf)Arguments
table | unusedSelf | unused parameter |
string | that | will be displayed on console |
1751 | function Player.consoleCommandReloadIKChains(unusedSelf) |
1752 | local player = g_currentMission.player |
1753 | local style = player.model.style |
1754 | |
1755 | local newModel = PlayerModel.new() |
1756 | newModel:load(player.model.style.xmlFilename, true, player.isOwner, true, function(_, success, _) |
1757 | if success then |
1758 | player:setModel(newModel) |
1759 | player:setStyle(style, false) |
1760 | |
1761 | g_messageCenter:publish(MessageType.PLAYER_STYLE_CHANGED, style, player.userId) |
1762 | |
1763 | log("Finished reload") |
1764 | end |
1765 | end, nil, nil) |
1766 | end |
consoleCommandThirdPersonView
DescriptionToggle player debug info displayDefinition
consoleCommandThirdPersonView()Return Values
string | that | will be displayed on console |
2766 | function Player:consoleCommandThirdPersonView() |
2767 | self:setThirdPersonViewActive(not self.thirdPersonViewActive) |
2768 | |
2769 | return "Player Third Person = " .. tostring(self.thirdPersonViewActive) |
2770 | end |
consoleCommandToggleFlightMode
DescriptionToggle flight modeDefinition
consoleCommandToggleFlightMode()Return Values
string | that | will be displayed on console |
1652 | function Player:consoleCommandToggleFlightMode() |
1653 | local usage = "Use key J to en-/disable flight mode, keys Q and E change the altitude. No Hud Mode was moved to gsHudVisibility" |
1654 | g_flightModeEnabled = not g_flightModeEnabled |
1655 | if not g_flightModeEnabled then |
1656 | self.debugFlightMode = false -- force reset flight mode |
1657 | end |
1658 | |
1659 | if GS_IS_MOBILE_VERSION then |
1660 | g_currentMission:onLeaveVehicle() |
1661 | end |
1662 | if g_flightModeEnabled then |
1663 | print(usage) |
1664 | end |
1665 | return "PlayerFlightMode = " .. tostring(g_flightModeEnabled) |
1666 | end |
consoleCommandToggleNoClipMode
DescriptionToggle player CCT no clip modeDefinition
consoleCommandToggleNoClipMode()Code
1670 | function Player:consoleCommandToggleNoClipMode(disableTerrainCollision) |
1671 | local usage = "Usage: gsPlayerNoClip [disableTerrainCollision]" |
1672 | local ret |
1673 | disableTerrainCollision = Utils.stringToBoolean(disableTerrainCollision) |
1674 | |
1675 | self.noClipEnabled = not self.noClipEnabled |
1676 | if self.noClipEnabled then |
1677 | self.cctMovementCollisionMaskBackup = self.cctMovementCollisionMask |
1678 | self.cctMovementCollisionMask = (disableTerrainCollision and 0) or CollisionFlag.TERRAIN |
1679 | ret = string.format("Enabled player noClip mode (%s)", (disableTerrainCollision and "including terrain") or "excluding terrain") |
1680 | else |
1681 | self.cctMovementCollisionMask = self.cctMovementCollisionMaskBackup |
1682 | self.cctMovementCollisionMaskBackup = nil |
1683 | ret = "Disabled player noClip mode" |
1684 | end |
1685 | |
1686 | return string.format("%s\n%s", ret, usage) |
1687 | end |
consoleCommandTogglePickupRaycastDebug
DescriptionToggle player pickup raycast debug: displays nodeId, node name, colMask and triggerProperty of hit nodesDefinition
consoleCommandTogglePickupRaycastDebug()Code
1722 | function Player:consoleCommandTogglePickupRaycastDebug() |
1723 | self.pickupRaycastDebugEnabled = not self.pickupRaycastDebugEnabled |
1724 | return "pickupRaycastDebugEnabled=" .. tostring(self.pickupRaycastDebugEnabled) |
1725 | end |
consoleCommandTogglePlayerDebug
DescriptionToggle player debug info displayDefinition
consoleCommandTogglePlayerDebug()Return Values
string | that | will be displayed on console |
2758 | function Player:consoleCommandTogglePlayerDebug() |
2759 | self.baseInformation.isInDebug = not self.baseInformation.isInDebug |
2760 | return "Player Debug = " .. tostring(self.baseInformation.isInDebug) |
2761 | end |
consoleCommandToggleSuperStrongMode
DescriptionToggle super-strength modeDefinition
consoleCommandToggleSuperStrongMode()Code
1700 | function Player:consoleCommandToggleSuperStrongMode() |
1701 | if self.superStrengthEnabled then |
1702 | self.superStrengthEnabled = false |
1703 | Player.MAX_PICKABLE_OBJECT_MASS = self.superStrengthPickupMassBackup |
1704 | Player.MAX_PICKABLE_OBJECT_DISTANCE = self.superStrengthPickupDistanceBackup |
1705 | self.superStrengthPickupMassBackup = nil |
1706 | |
1707 | return "Player now has normal strength" |
1708 | else |
1709 | self.superStrengthEnabled = true |
1710 | self.superStrengthPickupMassBackup = Player.MAX_PICKABLE_OBJECT_MASS |
1711 | Player.MAX_PICKABLE_OBJECT_MASS = 50 |
1712 | self.superStrengthPickupDistanceBackup = Player.MAX_PICKABLE_OBJECT_DISTANCE |
1713 | Player.MAX_PICKABLE_OBJECT_DISTANCE = 6.0 |
1714 | |
1715 | return "Player now has super-strength and increased range" |
1716 | end |
1717 | end |
consoleCommandToggleWoodCuttingMaker
DescriptionToggle wood cutting markerDefinition
consoleCommandToggleWoodCuttingMaker(table unusedSelf)Arguments
table | unusedSelf | unused parameter |
string | that | will be displayed on console |
1693 | function Player.consoleCommandToggleWoodCuttingMaker(unusedSelf) |
1694 | g_woodCuttingMarkerEnabled = not g_woodCuttingMarkerEnabled |
1695 | return "WoodCuttingMarker = " .. tostring(g_woodCuttingMarkerEnabled) |
1696 | end |
debugDraw
DescriptionPrints player debug information regarding motion and input.Definition
debugDraw()Code
2521 | function Player:debugDraw() |
2522 | if (self.baseInformation.isInDebug) then |
2523 | setTextColor(1, 0, 0, 1) |
2524 | local line = 0.96 |
2525 | renderText(0.05, line, 0.02, "[motion]"); line = line - 0.02 |
2526 | renderText(0.05, line, 0.02, string.format("isOnGround(%s) ", tostring(self.baseInformation.isOnGround))); line = line - 0.02 |
2527 | renderText(0.05, line, 0.02, string.format("lastPosition(%3.4f, %3.4f)", self.baseInformation.lastPositionX, self.baseInformation.lastPositionZ)); line = line - 0.02 |
2528 | renderText(0.05, line, 0.02, string.format("distanceCovered(%.2f)", self.motionInformation.coveredGroundDistance)); line = line - 0.02 |
2529 | renderText(0.05, line, 0.02, string.format("inWater(%s)", tostring(self.baseInformation.isInWater))); line = line - 0.02 |
2530 | renderText(0.05, line, 0.02, string.format("currentSpeed(%.3f) speedY(%.3f)", self.motionInformation.currentSpeed, self.motionInformation.currentSpeedY)); line = line - 0.02 |
2531 | renderText(0.05, line, 0.02, string.format("rotY(%.3f)", self.graphicsRotY)); line = line - 0.02 |
2532 | renderText(0.05, line, 0.02, string.format("estimatedYaw(%.3f)", self.estimatedYawVelocity)); line = line - 0.02 |
2533 | renderText(0.05, line, 0.02, string.format("cameraRotY(%.3f)", self.cameraRotY)); line = line - 0.02 |
2534 | |
2535 | |
2536 | setTextColor(0, 1, 0, 1) |
2537 | line = line - 0.02 |
2538 | renderText(0.05, line, 0.02, "[input]"); line = line - 0.02 |
2539 | renderText(0.05, line, 0.02, string.format("right(%3.4f)", self.inputInformation.moveRight)) |
2540 | line = line - 0.02 |
2541 | renderText(0.05, line, 0.02, string.format("forward(%3.4f)", self.inputInformation.moveForward)) |
2542 | line = line - 0.02 |
2543 | renderText(0.05, line, 0.02, string.format("pitch(%3.4f)", self.inputInformation.pitchCamera)) |
2544 | line = line - 0.02 |
2545 | renderText(0.05, line, 0.02, string.format("yaw(%3.4f)", self.inputInformation.yawCamera)) |
2546 | line = line - 0.02 |
2547 | renderText(0.05, line, 0.02, string.format("runAxis(%3.4f)", self.inputInformation.runAxis)) |
2548 | line = line - 0.02 |
2549 | renderText(0.05, line, 0.02, string.format("crouchState(%s)", tostring(self.inputInformation.crouchState))) |
2550 | line = line - 0.02 |
2551 | renderText(0.05, line, 0.02, string.format("interactState(%s)", tostring(self.inputInformation.interactState))) |
2552 | end |
2553 | end |
delete
DescriptionDeleteDefinition
delete()Code
375 | function Player:delete() |
376 | self.isDeleting = true |
377 | |
378 | if self.isOwner then -- only remove action events if this Player instance was controller by the current user |
379 | g_messageCenter:unsubscribeAll(self) |
380 | self:removeActionEvents() |
381 | end |
382 | |
383 | if self.isCarryingObject then |
384 | if g_server ~= nil then |
385 | self:pickUpObject(false) |
386 | end |
387 | end |
388 | |
389 | g_currentMission:removeMapHotspot(self.playerHotspot) |
390 | self.playerHotspot:delete() |
391 | |
392 | if self.pickedUpObjectOverlay ~= nil then |
393 | self.pickedUpObjectOverlay:delete() |
394 | self.aimOverlay:delete() |
395 | self.brushOverlay:delete() |
396 | self.petOverlay:delete() |
397 | end |
398 | |
399 | if self:hasHandtoolEquipped() then |
400 | self.baseInformation.currentHandtool:onDeactivate() |
401 | self.baseInformation.currentHandtool:delete() |
402 | self.baseInformation.currentHandtool = nil |
403 | end |
404 | |
405 | self.model:delete() |
406 | |
407 | removeCCT(self.controllerIndex) |
408 | delete(self.rootNode) |
409 | delete(self.graphicsRootNode) |
410 | |
411 | self.playerStateMachine:delete() |
412 | self.hudUpdater:delete() |
413 | self:deleteStartleAnimalData() |
414 | |
415 | if self.foliageBendingId ~= nil then |
416 | g_currentMission.foliageBendingSystem:destroyObject(self.foliageBendingId) |
417 | self.foliageBendingId = nil |
418 | end |
419 | |
420 | if self.isOwner then |
421 | removeConsoleCommand("gsPlayerFlightMode") |
422 | removeConsoleCommand("gsWoodCuttingMarkerVisiblity") |
423 | removeConsoleCommand("gsPlayerDebug") |
424 | removeConsoleCommand("gsPlayerNoClip") |
425 | removeConsoleCommand("gsPlayerThirdPerson") |
426 | removeConsoleCommand("gsPlayerIKChainsReload") |
427 | removeConsoleCommand("gsTip") |
428 | removeConsoleCommand("gsPlayerSuperStrength") |
429 | --#debug removeConsoleCommand("gsPlayerRaycastDebug") |
430 | end |
431 | |
432 | Player:superClass().delete(self) |
433 | end |
deleteStartleAnimalData
DescriptionRemove animal sound timer and sound itself (deprecated?)Definition
deleteStartleAnimalData()Code
1729 | function Player:deleteStartleAnimalData() |
1730 | if (self.startleAnimalSoundTimerId) then |
1731 | removeTimer(self.startleAnimalSoundTimerId) |
1732 | self.startleAnimalSoundTimerId = nil |
1733 | end |
1734 | self:deleteStartleAnimalSound() |
1735 | end |
deleteStartleAnimalSound
DescriptionRemove animal sound(deprecated?)Definition
deleteStartleAnimalSound()Code
1739 | function Player:deleteStartleAnimalSound() |
1740 | if (self.startleAnimalSoundNode) then |
1741 | delete(self.startleAnimalSoundNode) |
1742 | self.startleAnimalSoundNode = nil |
1743 | end |
1744 | self.startleAnimalSoundTimerId = nil |
1745 | end |
draw
DescriptionDraws overlay informationDefinition
draw()Code
1465 | function Player:draw() |
1466 | if self:getIsInputAllowed() then |
1467 | if self:hasHandtoolEquipped() then |
1468 | self.baseInformation.currentHandtool:draw() |
1469 | else |
1470 | if not g_noHudModeEnabled then |
1471 | if self.playerStateMachine:isAvailable("animalPet") then |
1472 | self.petOverlay:render() |
1473 | elseif self.playerStateMachine:isAvailable("animalInteract") and self.playerStateMachine:getState("animalInteract"):getCanClean() then |
1474 | self.brushOverlay:render() |
1475 | elseif not self.isCarryingObject and self.isObjectInRange then |
1476 | self.pickedUpObjectOverlay:render() |
1477 | else |
1478 | self.aimOverlay:render() |
1479 | end |
1480 | end |
1481 | end |
1482 | end |
1483 | end |
drawUIInfo
DescriptionRenders UI information for the playerDefinition
drawUIInfo()Code
1442 | function Player:drawUIInfo() |
1443 | if self.isClient and self.isControlled and not self.isEntered then |
1444 | if not g_gui:getIsGuiVisible() and not g_noHudModeEnabled and g_gameSettings:getValue(GameSettings.SETTING.SHOW_MULTIPLAYER_NAMES) then |
1445 | local x, y, z = getTranslation(self.graphicsRootNode) |
1446 | local x1, y1, z1 = getWorldTranslation(getCamera()) |
1447 | local diffX = x - x1 |
1448 | local diffY = y - y1 |
1449 | local diffZ = z - z1 |
1450 | local dist = MathUtil.vector3LengthSq(diffX, diffY, diffZ) |
1451 | if dist <= 100 * 100 then |
1452 | y = y + self.baseInformation.tagOffset[2] |
1453 | |
1454 | local user = g_currentMission.userManager:getUserByUserId(self.userId) |
1455 | if user ~= nil then |
1456 | Utils.renderTextAtWorldPosition(x, y, z, user:getNickname(), getCorrectTextSize(0.02), 0) |
1457 | end |
1458 | end |
1459 | end |
1460 | end |
1461 | end |
equipHandtool
DescriptionDefinitionequipHandtool()Code
1973 | function Player:equipHandtool(handtoolFilename, force, noEventSend, equippedCallbackFunction, equippedCallbackTarget) |
1974 | if self.isOwner then -- make sure we only change depth of field for locally controlled player instances |
1975 | if handtoolFilename == nil or handtoolFilename == "" then |
1976 | g_depthOfFieldManager:reset() |
1977 | else |
1978 | g_depthOfFieldManager:setManipulatedParams(0.8, 0.6, nil, nil, nil) |
1979 | end |
1980 | end |
1981 | |
1982 | if handtoolFilename ~= nil and handtoolFilename ~= "" and not fileExists(handtoolFilename) then |
1983 | Logging.error("Unable to equip handTool '%s'. Config file does not exist!", handtoolFilename) |
1984 | end |
1985 | |
1986 | PlayerSetHandToolEvent.sendEvent(self, handtoolFilename, force, noEventSend) |
1987 | |
1988 | local arguments = { |
1989 | equippedCallbackFunction = equippedCallbackFunction, |
1990 | equippedCallbackTarget = equippedCallbackTarget |
1991 | } |
1992 | |
1993 | if self:hasHandtoolEquipped() then |
1994 | if self.baseInformation.currentHandtool.configFileName:lower() ~= handtoolFilename:lower() or handtoolFilename == "" or force then |
1995 | self.baseInformation.currentHandtool:onDeactivate() |
1996 | self.baseInformation.currentHandtool:delete() |
1997 | self.baseInformation.currentHandtool = nil |
1998 | end |
1999 | if handtoolFilename ~= "" then |
2000 | self:loadHandTool(handtoolFilename, self.handToolLoaded, arguments) |
2001 | end |
2002 | else |
2003 | if handtoolFilename ~= "" then |
2004 | self:loadHandTool(handtoolFilename, self.handToolLoaded, arguments) |
2005 | end |
2006 | end |
2007 | end |
getCanEnterRideable
DescriptionVehicle can be enteredDefinition
getCanEnterRideable()Return Values
bool | canBeEntered | vehicle is in range to be entered |
1328 | function Player:getCanEnterRideable() |
1329 | if self.canEnterVehicle then |
1330 | local vehicle = g_currentMission.interactiveVehicleInRange |
1331 | if vehicle ~= nil then |
1332 | if SpecializationUtil.hasSpecialization(Rideable, vehicle.specializations) then |
1333 | return true |
1334 | end |
1335 | end |
1336 | end |
1337 | |
1338 | return false |
1339 | end |
getCanEnterVehicle
DescriptionVehicle can be enteredDefinition
getCanEnterVehicle()Return Values
bool | canBeEntered | vehicle is in range to be entered |
1321 | function Player:getCanEnterVehicle() |
1322 | return self.canEnterVehicle and not self:getCanEnterRideable() |
1323 | end |
getDesiredSpeed
DescriptionDefinitiongetDesiredSpeed()Code
2557 | function Player:getDesiredSpeed() |
2558 | local inputRight = self.inputInformation.moveRight |
2559 | local inputForward = self.inputInformation.moveForward |
2560 | |
2561 | if ((inputForward ~= 0.0) or (inputRight ~= 0.0)) then |
2562 | local isSwimming = self.playerStateMachine:isActive("swim") |
2563 | local isCrouching = self.playerStateMachine:isActive("crouch") |
2564 | local isFalling = self.playerStateMachine:isActive("fall") |
2565 | local isUsingHandtool = self:hasHandtoolEquipped() |
2566 | local baseSpeed = self.motionInformation.maxWalkingSpeed |
2567 | if isFalling then |
2568 | baseSpeed = self.motionInformation.maxFallingSpeed |
2569 | elseif isSwimming then |
2570 | baseSpeed = self.motionInformation.maxSwimmingSpeed |
2571 | elseif isCrouching then |
2572 | baseSpeed = self.motionInformation.maxCrouchingSpeed |
2573 | end |
2574 | |
2575 | local magnitude = math.sqrt(inputRight * inputRight + inputForward * inputForward) |
2576 | local desiredSpeed = MathUtil.clamp(magnitude, 0.0, 1.0) * baseSpeed |
2577 | local inputRun = self.inputInformation.runAxis |
2578 | |
2579 | if (inputRun > 0.0) and not (isSwimming or isCrouching or isUsingHandtool) then -- check if we are running |
2580 | local runningSpeed = self.motionInformation.maxRunningSpeed |
2581 | |
2582 | if g_addTestCommands then |
2583 | runningSpeed = self.motionInformation.maxPresentationRunningSpeed |
2584 | elseif g_addCheatCommands and (g_currentMission.isMasterUser or g_currentMission:getIsServer()) then |
2585 | runningSpeed = self.motionInformation.maxCheatRunningSpeed |
2586 | end |
2587 | desiredSpeed = math.max(desiredSpeed + (runningSpeed - desiredSpeed) * MathUtil.clamp(inputRun, 0.0, 1.0), desiredSpeed) |
2588 | end |
2589 | return desiredSpeed |
2590 | end |
2591 | return 0.0 |
2592 | end |
getEquippedHandtoolFilename
DescriptionGet the configuration filename of a currently equipped hand tool.Definition
getEquippedHandtoolFilename()Return Values
string | Filename | of currently equipped hand tool or empty string if no hand tool is equipped |
2055 | function Player:getEquippedHandtoolFilename() |
2056 | return self.baseInformation.currentHandtool ~= nil and self.baseInformation.currentHandtool.configFileName or "" |
2057 | end |
getIsInputAllowed
DescriptionA function to check if input is allowed. Player is entered and is a client as well as the gui is visible.Definition
getIsInputAllowed()Return Values
bool | true | if input is allowed. |
752 | function Player:getIsInputAllowed() |
753 | return self.isEntered and self.isClient and not g_gui:getIsGuiVisible() |
754 | end |
getIsRideStateAvailable
DescriptionDefinitiongetIsRideStateAvailable()Code
3195 | function Player:getIsRideStateAvailable() |
3196 | if not self.playerStateMachine:isActive("animalRide") then |
3197 | return self.playerStateMachine:isAvailable("animalRide") |
3198 | end |
3199 | |
3200 | return false |
3201 | end |
getParentComponent
DescriptionGets the parent nodeDefinition
getParentComponent(table node)Arguments
table | node | this parameter is unused in this function |
table | returns | the graphics root node |
369 | function Player:getParentComponent(node) |
370 | return self.graphicsRootNode |
371 | end |
getPositionData
DescriptionLet position information of the root node of the playerDefinition
getPositionData()Return Values
float | posX | x position of player |
float | posY | y position of player |
float | posZ | z position of player |
float | graphicsRotY | rotation of the player |
1296 | function Player:getPositionData() |
1297 | local posX, posY, posZ = getTranslation(self.rootNode) |
1298 | if self.isClient and self.isControlled and self.isEntered then |
1299 | return posX, posY, posZ, self.rotY |
1300 | else |
1301 | return posX, posY, posZ, self.graphicsRotY + math.pi |
1302 | end |
1303 | end |
getUpdatePriority
DescriptionCalculate a priority value from the position of the root node and the clpi distanceDefinition
getUpdatePriority(float skipCount, float x, float y, float z, float coeff, table connection)Arguments
float | skipCount | |
float | x | world x position |
float | y | world y position |
float | z | world z position |
float | coeff | parameter is unused |
table | connection | structure containing connection information |
float | returns | calculated priority |
1639 | function Player:getUpdatePriority(skipCount, x, y, z, coeff, connection, isGuiVisible) |
1640 | if self.owner == connection then |
1641 | return 50 |
1642 | end |
1643 | local x1, y1, z1 = getTranslation(self.rootNode) |
1644 | local dist = MathUtil.vector3Length(x1 - x, y1 - y, z1 - z) |
1645 | local clipDist = self.clipDistance |
1646 | return (1 - dist / clipDist) * 0.8 + 0.5 * skipCount * 0.2 |
1647 | end |
handToolLoaded
DescriptionCalled when hand tool was fully loadedDefinition
handToolLoaded(table handTool)Arguments
table | handTool | hand tool |
2012 | function Player:handToolLoaded(handTool, arguments) |
2013 | if self.baseInformation.currentHandtool ~= nil then |
2014 | self.baseInformation.currentHandtool:onDeactivate() |
2015 | self.baseInformation.currentHandtool:delete() |
2016 | self.baseInformation.currentHandtool = nil |
2017 | end |
2018 | |
2019 | self.baseInformation.currentHandtool = handTool |
2020 | |
2021 | handTool:setHandNode(self.model.rightArmToolNode) |
2022 | handTool:onActivate(self:getIsInputAllowed()) |
2023 | |
2024 | if handTool.targets ~= nil then |
2025 | local ikChains = self.model:getIKChains() |
2026 | for ikChainId, target in pairs(handTool.targets) do |
2027 | IKUtil.setTarget(ikChains, ikChainId, target) |
2028 | end |
2029 | self:setIKDirty() |
2030 | end |
2031 | |
2032 | local equippedCallbackFunction = arguments.equippedCallbackFunction |
2033 | local equippedCallbackTarget = arguments.equippedCallbackTarget |
2034 | |
2035 | if equippedCallbackFunction ~= nil then |
2036 | equippedCallbackFunction(equippedCallbackTarget, handTool) |
2037 | end |
2038 | end |
hasHandtoolEquipped
DescriptionDefinitionhasHandtoolEquipped()Code
2048 | function Player:hasHandtoolEquipped() |
2049 | return self.baseInformation.currentHandtool ~= nil |
2050 | end |
load
DescriptionLoading player informationDefinition
load(string xmlFilename, table creatorConnection, bool isOwner)Arguments
string | xmlFilename | XML filename containing player information |
table | creatorConnection | |
bool | isOwner | true is current player is owner |
278 | function Player:load(creatorConnection, isOwner) |
279 | self.networkInformation.creatorConnection = creatorConnection |
280 | self.isOwner = isOwner |
281 | |
282 | -- Root node based on physics. CCT is attached here |
283 | self.rootNode = createTransformGroup("PlayerCCT") |
284 | link(getRootNode(), self.rootNode) |
285 | -- Root node that decides client position (directly controlled by player for smoothness) |
286 | self.graphicsRootNode = createTransformGroup("player_graphicsRootNode") |
287 | link(getRootNode(), self.graphicsRootNode) |
288 | |
289 | -- Create the player camera. We'll move this camera between targets such as the 1p target or the 3p target. |
290 | self.cameraNode = createCamera("player_camera", math.rad(70), 0.15, 6000) |
291 | self.fovY = calculateFovY(self.cameraNode) |
292 | setFovY(self.cameraNode, self.fovY) |
293 | |
294 | self.thirdPersonLookatNode = createTransformGroup("thirdPersonLookatNode") |
295 | link(self.graphicsRootNode, self.thirdPersonLookatNode) |
296 | --local radius, height = self.model:getCapsuleSize() |
297 | --local headHeight = height + radius |
298 | setTranslation(self.thirdPersonLookatNode, 0, 0, 0) |
299 | --setTranslation(self.thirdPersonLookatNode, 0, headHeight, 0) |
300 | |
301 | self.thirdPersonLookfromNode = createTransformGroup("thirdPersonLookfromNode") |
302 | link(self.thirdPersonLookatNode, self.thirdPersonLookfromNode) |
303 | --setTranslation(self.thirdPersonLookfromNode, 0, 0, -5) -- 5m camera distance |
304 | setTranslation(self.thirdPersonLookfromNode, 0, 0, -2) -- 5m camera distance |
305 | |
306 | self:updateCameraModelTarget() |
307 | |
308 | self.foliageBendingNode = createTransformGroup("player_foliageBendingNode") |
309 | link(self.graphicsRootNode, self.foliageBendingNode) |
310 | |
311 | self.playerStateMachine:load() |
312 | |
313 | self.isObjectInRange = false |
314 | self.isCarryingObject = false |
315 | self.pickedUpObject = nil |
316 | |
317 | local uiScale = g_gameSettings:getValue("uiScale") |
318 | |
319 | local pickupWidth, pickupHeight = getNormalizedScreenValues(80 * uiScale, 80 * uiScale) |
320 | self.pickedUpObjectOverlay = Overlay.new(g_baseHUDFilename, 0.5, 0.5, pickupWidth, pickupHeight) |
321 | self.pickedUpObjectOverlay:setAlignment(Overlay.ALIGN_VERTICAL_MIDDLE, Overlay.ALIGN_HORIZONTAL_CENTER) |
322 | self.pickedUpObjectOverlay:setUVs(GuiUtils.getUVs{0, 138, 80, 80}) |
323 | self.pickedUpObjectOverlay:setColor(1, 1, 1, 0.3) |
324 | |
325 | local aimWidth, aimHeight = getNormalizedScreenValues(20 * uiScale, 20 * uiScale) |
326 | self.aimOverlay = Overlay.new(g_baseHUDFilename, 0.5, 0.5, aimWidth, aimHeight) |
327 | self.aimOverlay:setAlignment(Overlay.ALIGN_VERTICAL_MIDDLE, Overlay.ALIGN_HORIZONTAL_CENTER) |
328 | self.aimOverlay:setUVs(GuiUtils.getUVs{0, 48, 48, 48}) |
329 | self.aimOverlay:setColor(1, 1, 1, 0.3) |
330 | |
331 | local brushWidth, brushHeight = getNormalizedScreenValues(75 * uiScale, 75 * uiScale) |
332 | self.brushOverlay = Overlay.new(g_baseHUDFilename, 0.5, 0.5, brushWidth, brushHeight) |
333 | self.brushOverlay:setAlignment(Overlay.ALIGN_VERTICAL_MIDDLE, Overlay.ALIGN_HORIZONTAL_CENTER) |
334 | self.brushOverlay:setUVs(GuiUtils.getUVs{307, 494, 75, 75}) |
335 | self.brushOverlay:setColor(1, 1, 1, 0.3) |
336 | |
337 | local petWidth, petHeight = getNormalizedScreenValues(75 * uiScale, 75 * uiScale) |
338 | self.petOverlay = Overlay.new(g_baseHUDFilename, 0.5, 0.5, petWidth, petHeight) |
339 | self.petOverlay:setAlignment(Overlay.ALIGN_VERTICAL_MIDDLE, Overlay.ALIGN_HORIZONTAL_CENTER) |
340 | self.petOverlay:setUVs(GuiUtils.getUVs{307, 419, 75, 75}) |
341 | self.petOverlay:setColor(1, 1, 1, 0.3) |
342 | |
343 | |
344 | self:moveToAbsoluteInternal(0, -200, 0) |
345 | |
346 | self:rebuildCCT() |
347 | |
348 | self.lockedInput = false |
349 | |
350 | if self.isOwner then |
351 | addConsoleCommand("gsPlayerFlightMode", "Enables/disables the flight mode toggle (key J). Use keys Q and E to change altitude", "consoleCommandToggleFlightMode", self) |
352 | addConsoleCommand("gsWoodCuttingMarkerVisiblity", "Enables/disables chainsaw woodcutting marker", "Player.consoleCommandToggleWoodCuttingMaker", nil) |
353 | addConsoleCommand("gsPlayerDebug", "Enables/disables player debug information", "consoleCommandTogglePlayerDebug", self) |
354 | addConsoleCommand("gsPlayerNoClip", "Enables/disables player no clip/collision mode. Use 'gsPlayerNoClip true' to also turn of terrain collision", "consoleCommandToggleNoClipMode", self) |
355 | if g_addTestCommands then |
356 | addConsoleCommand("gsTip", "Tips a fillType into a trigger", "consoleCommandTip", self) |
357 | addConsoleCommand("gsPlayerIKChainsReload", "Reloads player IKChains", "Player.consoleCommandReloadIKChains", nil) |
358 | addConsoleCommand("gsPlayerSuperStrength", "Enables/disables player super strength", "consoleCommandToggleSuperStrongMode", self) |
359 | --#debug addConsoleCommand("gsPlayerRaycastDebug", "Enables/disables player pickup raycast debug information", "consoleCommandTogglePickupRaycastDebug", self) |
360 | addConsoleCommand("gsPlayerThirdPerson", "Enables/disables player third person view", "consoleCommandThirdPersonView", self) |
361 | end |
362 | end |
363 | end |
loadHandTool
DescriptionLoading hand tools for the playerDefinition
loadHandTool(string xmlFilename)Arguments
string | xmlFilename | XML filename |
table | returns | the handtool |
1931 | function Player:loadHandTool(xmlFilename, asyncCallbackFunction, asyncCallbackArguments) |
1932 | if GS_IS_CONSOLE_VERSION and not fileExists(xmlFilename) then |
1933 | return nil |
1934 | end |
1935 | local dataStoreItem = g_storeManager:getItemByXMLFilename(xmlFilename) |
1936 | if dataStoreItem ~= nil then |
1937 | local storeItemXmlFilename = dataStoreItem.xmlFilename |
1938 | local xmlFile = loadXMLFile("TempXML", storeItemXmlFilename) |
1939 | local handToolType = getXMLString(xmlFile, "handTool.handToolType") |
1940 | delete(xmlFile) |
1941 | |
1942 | if handToolType ~= nil then |
1943 | local classObject = HandTool.handToolTypes[handToolType] |
1944 | if classObject == nil then |
1945 | local modName, _ = Utils.getModNameAndBaseDirectory(storeItemXmlFilename) |
1946 | if modName ~= nil then |
1947 | handToolType = modName.."."..handToolType |
1948 | classObject = HandTool.handToolTypes[handToolType] |
1949 | end |
1950 | end |
1951 | local handTool = nil |
1952 | if classObject ~= nil then |
1953 | handTool = classObject.new(self.isServer, self.isClient) |
1954 | else |
1955 | Logging.devError("Error: Invalid handtool type '%s'", handToolType) |
1956 | end |
1957 | if handTool ~= nil then |
1958 | if not handTool:load(storeItemXmlFilename, self, asyncCallbackFunction, asyncCallbackArguments) then |
1959 | Logging.devError("Error: Failed to load handtool '%s'", storeItemXmlFilename) |
1960 | handTool:delete() |
1961 | handTool = nil |
1962 | end |
1963 | end |
1964 | |
1965 | return handTool |
1966 | end |
1967 | end |
1968 | return nil |
1969 | end |
lockInput
DescriptionLocks player inputDefinition
lockInput(bool locked)Arguments
bool | locked | if true, will lock input |
1314 | function Player:lockInput(locked) |
1315 | self.lockedInput = locked |
1316 | end |
mouseEvent
DescriptionFunction called when mouse is moved (call from BaseMission).Definition
mouseEvent(float posX, float posY, bool isDown, bool isUp, button)Arguments
float | posX | position of the mouse |
float | posY | position of the mouse |
bool | isDown | |
bool | isUp | |
button |
746 | function Player:mouseEvent(posX, posY, isDown, isUp, button) |
747 | end |
movePlayer
DescriptionDefinitionmovePlayer()Code
2408 | function Player:movePlayer(dt, movementX, movementY, movementZ) |
2409 | self.debugFlightCoolDown = self.debugFlightCoolDown - 1 |
2410 | if self.debugFlightMode then |
2411 | movementY = self.inputInformation.moveUp * dt |
2412 | end |
2413 | |
2414 | self.networkInformation.tickTranslation[1] = self.networkInformation.tickTranslation[1] + movementX |
2415 | self.networkInformation.tickTranslation[2] = self.networkInformation.tickTranslation[2] + movementY |
2416 | self.networkInformation.tickTranslation[3] = self.networkInformation.tickTranslation[3] + movementZ |
2417 | moveCCT(self.controllerIndex, movementX, movementY, movementZ, self.cctMovementCollisionMask) |
2418 | |
2419 | self.networkInformation.index = self.networkInformation.index + 1 |
2420 | if not self.isServer then |
2421 | -- remove old history (above 100 entries) |
2422 | while table.getn(self.networkInformation.history) > 100 do |
2423 | table.remove(self.networkInformation.history, 1) |
2424 | end |
2425 | table.insert(self.networkInformation.history, {index=self.networkInformation.index, movementX=movementX, movementY=movementY, movementZ=movementZ}) |
2426 | end |
2427 | end |
moveRootNodeToAbsolute
DescriptionMoves the player to the given position, such that the root node is at x, y, zDefinition
moveRootNodeToAbsolute(float x, float y, float z)Arguments
float | x | new x position |
float | y | new y position |
float | z | new z position |
1378 | function Player:moveRootNodeToAbsolute(x, y, z) |
1379 | self:moveTo(x, y, z, true, true) |
1380 | end |
moveTo
DescriptionMoves the player to the given position, with the given y offset to the terrainDefinition
moveTo(float x, float y, float z, bool isAbsolute, bool isRootNode)Arguments
float | x | new x position |
float | y | new y position |
float | z | new z position |
bool | isAbsolute | if true, Y coordinate is in absolute, not calculated from terrain height |
bool | isRootNode | if true, coordinates are expected to be at the bottom of the player capsule, otherweise half capsule height will be added to y |
1348 | function Player:moveTo(x, y, z, isAbsolute, isRootNode) |
1349 | self:unequipHandtool() |
1350 | |
1351 | if not self.isServer and self.isOwner then |
1352 | g_client:getServerConnection():sendEvent(PlayerTeleportEvent.new(x, y, z, isAbsolute, isRootNode)) |
1353 | end |
1354 | if not isAbsolute then |
1355 | local terrainHeight = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, 300, z) |
1356 | y = terrainHeight + y |
1357 | end |
1358 | if not isRootNode then |
1359 | y = y + self.model.capsuleTotalHeight * 0.5 |
1360 | end |
1361 | self:moveToAbsoluteInternal(x, y, z) |
1362 | end |
moveToAbsolute
DescriptionMoves the player root node to the given position, such that the feet are at x, y, zDefinition
moveToAbsolute(float x, float y, float z)Arguments
float | x | new x position |
float | y | new y position |
float | z | new z position |
1369 | function Player:moveToAbsolute(x, y, z) |
1370 | self:moveTo(x, y, z, true, false) |
1371 | end |
moveToAbsoluteInternal
DescriptionMove player root node and graphics node to a specific position. Updates interpolation parametersDefinition
moveToAbsoluteInternal(float x, float y, float z)Arguments
float | x | new x position |
float | y | new y position |
float | z | new z position |
1423 | function Player:moveToAbsoluteInternal(x, y, z) |
1424 | setTranslation(self.rootNode, x, y, z) |
1425 | setTranslation(self.graphicsRootNode, x, y, z) |
1426 | |
1427 | self.networkInformation.interpolationTime:reset() |
1428 | self.networkInformation.interpolatorPosition:setPosition(x,y,z) |
1429 | self.networkInformation.updateTargetTranslationPhysicsIndex = -1 |
1430 | |
1431 | self.lastAnimPosX = x |
1432 | self.lastAnimPosY = y |
1433 | self.lastAnimPosZ = z |
1434 | self.walkDistance = 0 |
1435 | |
1436 | local _ |
1437 | self.baseInformation.lastPositionX, _, self.baseInformation.lastPositionZ = getTranslation(self.graphicsRootNode) |
1438 | end |
moveToExitPoint
DescriptionMoves player to vehicle exit nodeDefinition
moveToExitPoint(table exitVehicle)Arguments
table | exitVehicle | vehicle class that will be used to get the exit node to place the player |
1385 | function Player:moveToExitPoint(exitVehicle) |
1386 | if exitVehicle.getExitNode == nil then |
1387 | return |
1388 | end |
1389 | |
1390 | local exitPoint = exitVehicle:getExitNode() |
1391 | local x, y, z = getWorldTranslation(exitPoint) |
1392 | local terrainHeight = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, 300, z) |
1393 | |
1394 | y = math.max(terrainHeight + 0.1, y + 0.9) |
1395 | self:moveToAbsolute(x, y, z) |
1396 | local dx, _, dz = localDirectionToWorld(exitPoint, 0, 0, -1) |
1397 | self.rotY = MathUtil.getYRotationFromDirection(dx, dz) |
1398 | |
1399 | --self.targetGraphicsRotY = self.rotY |
1400 | --self.graphicsRotY = self.rotY |
1401 | --(I) setRotation(self.graphicsRootNode, 0, self.graphicsRotY, 0) |
1402 | setRotation(self.cameraNode, self.rotX, self.rotY, 0) |
1403 | end |
new
DescriptionCreating player and initializing member variablesDefinition
new(boolean isServer, boolean isClient)Arguments
boolean | isServer | is server |
boolean | isClient | is client |
table | instance | Instance of object |
77 | function Player.new(isServer, isClient) |
78 | local self = Object.new(isServer, isClient, Player_mt) |
79 | |
80 | self.isControlled = false |
81 | self.isOwner = false |
82 | self.isEntered = false |
83 | self.debugFlightModeWalkingSpeed = 0.016 |
84 | self.debugFlightModeRunningFactor = 1 |
85 | |
86 | self.model = PlayerModel.new() |
87 | self.model:loadEmpty() |
88 | |
89 | self.cctMovementCollisionMask = CollisionMask.PLAYER_MOVEMENT |
90 | |
91 | self.networkInformation = {} |
92 | self.networkInformation.creatorConnection = nil |
93 | self.networkInformation.history = {} |
94 | self.networkInformation.index = 0 |
95 | if self.isServer then |
96 | self.networkInformation.sendIndex = 0 |
97 | end |
98 | self.networkInformation.interpolationTime = InterpolationTime.new(1.2) |
99 | self.networkInformation.interpolatorPosition = InterpolatorPosition.new(0.0, 0.0, 0.0) |
100 | self.networkInformation.interpolatorQuaternion = InterpolatorQuaternion.new(0.0, 0.0, 0.0, 1.0) -- only used on server side for rotation of camera |
101 | self.networkInformation.interpolatorOnGround = InterpolatorValue.new(0.0) |
102 | self.networkInformation.tickTranslation = {0.0, 0.0, 0.0} |
103 | self.networkInformation.dirtyFlag = self:getNextDirtyFlag() |
104 | self.networkInformation.updateTargetTranslationPhysicsIndex = -1 |
105 | self.networkInformation.rotateObject = false |
106 | self.networkInformation.rotateObjectInputV = 0.0 |
107 | self.networkInformation.rotateObjectInputH = 0.0 |
108 | |
109 | self.motionInformation = {} |
110 | self.motionInformation.damping = 0.8 |
111 | self.motionInformation.mass = 80.0 -- in kg |
112 | self.motionInformation.maxAcceleration = 50.0 -- m/s^2 |
113 | self.motionInformation.maxDeceleration = 50.0 -- m/s^2 |
114 | self.motionInformation.gravity = -9.8 |
115 | |
116 | -- if getUserName() == "jkuijpers" then |
117 | -- -- real walking speed: 1.4, real running speed: 6.5, real swimming speed: 0.9 |
118 | -- self.motionInformation.maxIdleSpeed = 0.1 -- in m/s |
119 | -- self.motionInformation.maxWalkingSpeed = 1.4 -- in m/s 4 |
120 | -- self.motionInformation.maxRunningSpeed = 9.0 -- in m/s |
121 | -- self.motionInformation.maxSwimmingSpeed = 3.0 -- in m/s |
122 | -- self.motionInformation.maxCrouchingSpeed = 2.0 -- in m/s |
123 | -- self.motionInformation.maxFallingSpeed = 1.4 -- in m/s |
124 | -- self.motionInformation.maxCheatRunningSpeed = 9.0 -- in m/s |
125 | -- self.motionInformation.maxPresentationRunningSpeed = 9.0 -- in m/s |
126 | -- self.motionInformation.maxSpeedDelay = 0.1 -- in s (how long before max speed is reached) |
127 | -- self.motionInformation.brakeDelay = 0.001 -- in s (how long before velocity is null) |
128 | -- self.motionInformation.brakeForce = {0.0, 0.0, 0.0} -- in N (force to apply to stop the player gradually) |
129 | -- else |
130 | |
131 | self.motionInformation.maxIdleSpeed = 0.1 -- in m/s |
132 | self.motionInformation.maxWalkingSpeed = 4.0 -- in m/s |
133 | self.motionInformation.maxRunningSpeed = 9.0 -- in m/s |
134 | self.motionInformation.maxSwimmingSpeed = 3.0 -- in m/s |
135 | self.motionInformation.maxCrouchingSpeed = 2.0 -- in m/s |
136 | self.motionInformation.maxFallingSpeed = 6.0 -- in m/s |
137 | self.motionInformation.maxCheatRunningSpeed = 34.0 -- in m/s |
138 | self.motionInformation.maxPresentationRunningSpeed = 128.0 -- in m/s |
139 | self.motionInformation.maxSpeedDelay = 0.1 -- in s (how long before max speed is reached) |
140 | self.motionInformation.brakeDelay = 0.001 -- in s (how long before velocity is null) |
141 | self.motionInformation.brakeForce = {0.0, 0.0, 0.0} -- in N (force to apply to stop the player gradually) |
142 | -- end |
143 | self.motionInformation.currentGroundSpeed = 0.0 -- in m/s |
144 | self.motionInformation.minimumFallingSpeed = -0.00001 -- in m/s |
145 | self.motionInformation.coveredGroundDistance = 0.0 -- in m |
146 | self.motionInformation.currentCoveredGroundDistance = 0.0 |
147 | self.motionInformation.justMoved = false -- |
148 | self.motionInformation.isBraking = false |
149 | self.motionInformation.lastSpeed = 0.0 |
150 | self.motionInformation.currentSpeed = 0.0 |
151 | self.motionInformation.currentSpeedY = 0.0 |
152 | self.motionInformation.isReverse = false |
153 | self.motionInformation.desiredSpeed = 0.0 |
154 | self.motionInformation.jumpHeight = 1 -- in m |
155 | self.motionInformation.currentWorldDirX = 0.0 |
156 | self.motionInformation.currentWorldDirZ = 1.0 |
157 | self.motionInformation.currentSpeedX = 0.0 |
158 | self.motionInformation.currentSpeedZ = 0.0 |
159 | |
160 | self.baseInformation = {} |
161 | self.baseInformation.lastPositionX = 0.0 |
162 | self.baseInformation.lastPositionZ = 0.0 |
163 | self.baseInformation.isOnGround = true |
164 | self.baseInformation.isOnGroundPhysics = true |
165 | self.baseInformation.isCloseToGround = true |
166 | self.baseInformation.isInWater = false |
167 | self.baseInformation.waterDepth = 0 |
168 | self.baseInformation.wasInWater = false |
169 | self.baseInformation.waterLevel = -1.4 |
170 | self.baseInformation.waterCameraOffset = 0.3 |
171 | self.baseInformation.currentWaterCameraOffset = 0.0 |
172 | self.baseInformation.plungedInWater = false |
173 | self.baseInformation.plungedYVelocityThreshold = -2.0 |
174 | self.baseInformation.isInDebug = false |
175 | self.baseInformation.tagOffset = {0.0, 1.9, 0.0} |
176 | self.baseInformation.translationAlphaDifference = 0.0 |
177 | self.baseInformation.animDt = 0.0 |
178 | self.baseInformation.isCrouched = false |
179 | self.baseInformation.isUsingChainsawHorizontal = false |
180 | self.baseInformation.isUsingChainsawVertical = false |
181 | self.baseInformation.currentHandtool = nil |
182 | self.baseInformation.headBobTime = 0.0 |
183 | self.baseInformation.lastCameraAmplitudeScale = 0.0 |
184 | self.lastEstimatedForwardVelocity = 0.0 |
185 | |
186 | self.inputInformation = {} |
187 | self.inputInformation.moveForward = 0.0 |
188 | self.inputInformation.moveRight = 0.0 |
189 | self.inputInformation.moveUp = 0.0 -- for debug flight mode |
190 | self.inputInformation.pitchCamera = 0.0 |
191 | self.inputInformation.yawCamera = 0.0 |
192 | self.inputInformation.runAxis = 0.0 |
193 | self.inputInformation.crouchState = Player.BUTTONSTATES.RELEASED |
194 | self.inputInformation.interactState = Player.BUTTONSTATES.RELEASED |
195 | |
196 | -- These are the parameters for the input registration and the eventId |
197 | self.inputInformation.registrationList = {} |
198 | self.inputInformation.registrationList[InputAction.AXIS_MOVE_SIDE_PLAYER] = { eventId="", callback=self.onInputMoveSide, triggerUp=false, triggerDown=false, triggerAlways=true, activeType=Player.INPUT_ACTIVE_TYPE.IS_MOVEMENT, callbackState=nil, text="", textVisibility=false } |
199 | self.inputInformation.registrationList[InputAction.AXIS_MOVE_FORWARD_PLAYER] = { eventId="", callback=self.onInputMoveForward, triggerUp=false, triggerDown=false, triggerAlways=true, activeType=Player.INPUT_ACTIVE_TYPE.IS_MOVEMENT, callbackState=nil, text="", textVisibility=false } |
200 | self.inputInformation.registrationList[InputAction.AXIS_LOOK_LEFTRIGHT_PLAYER] = { eventId="", callback=self.onInputLookLeftRight, triggerUp=false, triggerDown=false, triggerAlways=true, activeType=Player.INPUT_ACTIVE_TYPE.IS_MOVEMENT, callbackState=nil, text="", textVisibility=false } |
201 | self.inputInformation.registrationList[InputAction.AXIS_LOOK_UPDOWN_PLAYER] = { eventId="", callback=self.onInputLookUpDown, triggerUp=false, triggerDown=false, triggerAlways=true, activeType=Player.INPUT_ACTIVE_TYPE.IS_MOVEMENT, callbackState=nil, text="", textVisibility=false } |
202 | self.inputInformation.registrationList[InputAction.AXIS_RUN] = { eventId="", callback=self.onInputRun, triggerUp=false, triggerDown=false, triggerAlways=true, activeType=Player.INPUT_ACTIVE_TYPE.IS_MOVEMENT, callbackState=nil, text="", textVisibility=false } |
203 | self.inputInformation.registrationList[InputAction.JUMP] = { eventId="", callback=self.onInputJump, triggerUp=false, triggerDown=true, triggerAlways=false, activeType=Player.INPUT_ACTIVE_TYPE.IS_MOVEMENT, callbackState=nil, text="", textVisibility=GS_IS_CONSOLE_VERSION } |
204 | -- TODO: read from game settings? also needs to be applied to PlayerStateCrouch.toggleMode. triggerAlways = not crouchToggleMode |
205 | self.inputInformation.registrationList[InputAction.CROUCH] = { eventId="", callback=self.onInputCrouch, triggerUp=false, triggerDown=true, triggerAlways=true, activeType=Player.INPUT_ACTIVE_TYPE.IS_MOVEMENT, callbackState=nil, text="", textVisibility=GS_IS_CONSOLE_VERSION } |
206 | self.inputInformation.registrationList[InputAction.ANIMAL_PET] = { eventId="", callback=self.onInputActivateObject, triggerUp=false, triggerDown=true, triggerAlways=false, activeType=Player.INPUT_ACTIVE_TYPE.IS_MOVEMENT, callbackState=nil, text="", textVisibility=true } |
207 | self.inputInformation.registrationList[InputAction.ROTATE_OBJECT_LEFT_RIGHT] = { eventId="", callback=self.onInputRotateObjectHorizontally, triggerUp=false, triggerDown=false, triggerAlways=true, activeType=Player.INPUT_ACTIVE_TYPE.IS_CARRYING, callbackState=nil, text=g_i18n:getText("action_rotateObjectHorizontally"), textVisibility=true } |
208 | self.inputInformation.registrationList[InputAction.ROTATE_OBJECT_UP_DOWN] = { eventId="", callback=self.onInputRotateObjectVertically, triggerUp=false, triggerDown=false, triggerAlways=true, activeType=Player.INPUT_ACTIVE_TYPE.IS_CARRYING, callbackState=nil, text=g_i18n:getText("action_rotateObjectVertically"), textVisibility=true } |
209 | self.inputInformation.registrationList[InputAction.ENTER] = { eventId="", callback=self.onInputEnter, triggerUp=false, triggerDown=true, triggerAlways=false, activeType=Player.INPUT_ACTIVE_TYPE.STARTS_ENABLED, callbackState=nil, text="", textVisibility=false } |
210 | self.inputInformation.registrationList[InputAction.TOGGLE_LIGHTS_FPS] = { eventId="", callback=self.onInputToggleLight, triggerUp=false, triggerDown=true, triggerAlways=false, activeType=Player.INPUT_ACTIVE_TYPE.STARTS_ENABLED, callbackState=nil, text="", textVisibility=false } |
211 | self.inputInformation.registrationList[InputAction.THROW_OBJECT] = { eventId="", callback=self.onInputThrowObject, triggerUp=false, triggerDown=true, triggerAlways=false, activeType=Player.INPUT_ACTIVE_TYPE.STARTS_DISABLED, callbackState=nil, text=g_i18n:getText("input_THROW_OBJECT"), textVisibility=true } |
212 | self.inputInformation.registrationList[InputAction.INTERACT] = { eventId="", callback=self.onInputInteract, triggerUp=true, triggerDown=true, triggerAlways=false, activeType=Player.INPUT_ACTIVE_TYPE.STARTS_DISABLED, callbackState=nil, text="", textVisibility=true } |
213 | self.inputInformation.registrationList[InputAction.SWITCH_HANDTOOL] = { eventId="", callback=self.onInputCycleHandTool, triggerUp=false, triggerDown=true, triggerAlways=false, activeType=Player.INPUT_ACTIVE_TYPE.STARTS_DISABLED, callbackState=nil, text=g_i18n:getText("input_SWITCH_HANDTOOL"), textVisibility=false } |
214 | self.inputInformation.registrationList[InputAction.DEBUG_PLAYER_ENABLE] = { eventId="", callback=self.onInputDebugFlyToggle, triggerUp=false, triggerDown=true, triggerAlways=false, activeType=Player.INPUT_ACTIVE_TYPE.IS_DEBUG, callbackState=nil, text="", textVisibility=false } |
215 | self.inputInformation.registrationList[InputAction.DEBUG_PLAYER_UP_DOWN] = { eventId="", callback=self.onInputDebugFlyUpDown, triggerUp=false, triggerDown=false, triggerAlways=true, activeType=Player.INPUT_ACTIVE_TYPE.IS_DEBUG, callbackState=nil, text="", textVisibility=false } |
216 | self.inputInformation.registrationList[InputAction.ACTIVATE_HANDTOOL] = { eventId="", callback=self.onInputActivateHandtool, triggerUp=false, triggerDown=true, triggerAlways=true, activeType=Player.INPUT_ACTIVE_TYPE.STARTS_DISABLED, callbackState=nil, text=g_i18n:getText("input_ACTIVATE_HANDTOOL"), textVisibility=false } |
217 | |
218 | -- Player movement lock flag |
219 | self.walkingIsLocked = false |
220 | |
221 | self.canRideAnimal = false |
222 | self.canEnterVehicle = false |
223 | |
224 | self.isTorchActive = false |
225 | |
226 | self.rotX = 0 |
227 | self.rotY = 0 |
228 | self.cameraRotY = 0 |
229 | |
230 | self.oldYaw = 0.0 -- in rad |
231 | self.newYaw = 0.0 -- in rad |
232 | self.estimatedYawVelocity = 0.0 -- in rad/s |
233 | |
234 | self.graphicsRotY = 0 |
235 | self.targetGraphicsRotY = 0 |
236 | |
237 | self.thirdPersonViewActive = false |
238 | |
239 | self.camera = 0 |
240 | |
241 | self.time = 0 |
242 | |
243 | self.clipDistance = 500 |
244 | self.waterY = -2000 |
245 | |
246 | self.lastAnimPosX = 0 |
247 | self.lastAnimPosY = 0 |
248 | self.lastAnimPosZ = 0 |
249 | |
250 | self.walkDistance = 0 |
251 | self.animUpdateTime = 0 |
252 | |
253 | self.allowPlayerPickUp = Platform.allowPlayerPickUp |
254 | |
255 | self.debugFlightMode = false |
256 | self.debugFlightCoolDown = 0 |
257 | |
258 | self.requestedFieldData = false |
259 | |
260 | self.playerStateMachine = PlayerStateMachine.new(self) |
261 | self.hudUpdater = PlayerHUDUpdater.new() |
262 | |
263 | self.farmId = FarmManager.SPECTATOR_FARM_ID |
264 | |
265 | self.cameraBobbingEnabled = g_gameSettings:getValue(GameSettings.SETTING.CAMERA_BOBBING) |
266 | |
267 | self.playerHotspot = PlayerHotspot.new() |
268 | self.playerHotspot:setPlayer(self) |
269 | |
270 | return self |
271 | end |
onEnter
DescriptionCalled when player enters mission. Sets player mesh visibility. Update traffic system with player info. Register player action events.Definition
onEnter(bool isControlling)Arguments
bool | isControlling | true if controlled |
1497 | function Player:onEnter(isControlling) |
1498 | self:raiseActive() |
1499 | if self.foliageBendingNode ~= nil and self.foliageBendingId == nil and g_currentMission.foliageBendingSystem then |
1500 | -- foliage bending |
1501 | self.foliageBendingId = g_currentMission.foliageBendingSystem:createRectangle(-0.5, 0.5, -0.5, 0.5, 0.4, self.foliageBendingNode) |
1502 | end |
1503 | |
1504 | if self.isServer then |
1505 | self:setOwner(self.networkInformation.creatorConnection) |
1506 | end |
1507 | if isControlling or self.isServer then |
1508 | self:raiseDirtyFlags(self.networkInformation.dirtyFlag) |
1509 | end |
1510 | |
1511 | self.isControlled = true |
1512 | if isControlling then |
1513 | g_messageCenter:subscribe(MessageType.INPUT_BINDINGS_CHANGED, self.onInputBindingsChanged, self) |
1514 | g_messageCenter:publish(MessageType.OWN_PLAYER_ENTERED) |
1515 | g_currentMission:addPauseListeners(self, Player.onPauseGame) |
1516 | setRotation(self.cameraNode, 0, 0, 0) |
1517 | setCamera(self.cameraNode) |
1518 | self.isEntered = true |
1519 | self:setVisibility(false) |
1520 | self:registerActionEvents() |
1521 | g_currentMission.environmentAreaSystem:setReferenceNode(self.cameraNode) |
1522 | else |
1523 | self:setVisibility(true) |
1524 | end |
1525 | |
1526 | self.playerHotspot:setOwnerFarmId(self.farmId) |
1527 | g_currentMission:addMapHotspot(self.playerHotspot) |
1528 | |
1529 | if self.isServer and not self.isEntered and g_currentMission.trafficSystem ~= nil and g_currentMission.trafficSystem.trafficSystemId ~= 0 then |
1530 | addTrafficSystemPlayer(g_currentMission.trafficSystem.trafficSystemId, self.graphicsRootNode) |
1531 | end |
1532 | self.isTorchActive = false |
1533 | end |
onEnterFarmhouse
DescriptionDefinitiononEnterFarmhouse()Code
2064 | function Player:onEnterFarmhouse() |
2065 | if self.isServer then |
2066 | local dogHouse = g_currentMission:getDoghouse(self.farmId) |
2067 | if dogHouse ~= nil and dogHouse.dog ~= nil and dogHouse.dog.entityFollow == self.rootNode then |
2068 | dogHouse.dog:teleportToSpawn() |
2069 | end |
2070 | end |
2071 | end |
onGhostAdd
DescriptionEmpty functionDefinition
onGhostAdd()Code
1627 | function Player:onGhostAdd() |
1628 | end |
onGhostRemove
DescriptionDeletes playerDefinition
onGhostRemove()Code
1621 | function Player:onGhostRemove() |
1622 | self:delete() |
1623 | end |
onInputActivateHandtool
DescriptionDefinitiononInputActivateHandtool()Code
3187 | function Player:onInputActivateHandtool(_, inputValue) |
3188 | if self:hasHandtoolEquipped() then |
3189 | self.baseInformation.currentHandtool.activatePressed = inputValue ~= 0 |
3190 | end |
3191 | end |
onInputActivateObject
DescriptionEvent function for interacting with an animalDefinition
onInputActivateObject()Code
3114 | function Player:onInputActivateObject(_, inputValue) |
3115 | self.playerStateMachine:activateState("animalPet") |
3116 | end |
onInputCrouch
DescriptionEvent function for crouching.Definition
onInputCrouch()Code
3031 | function Player:onInputCrouch(_, inputValue) |
3032 | if self.playerStateMachine:isAvailable("crouch") then |
3033 | self.playerStateMachine:activateState("crouch") |
3034 | end |
3035 | |
3036 | self.inputInformation.crouchState = Player.BUTTONSTATES.PRESSED |
3037 | end |
onInputCycleHandTool
DescriptionEvent function for cycling through available hand tools.Definition
onInputCycleHandTool(nil, nil, integer direction)Arguments
nil | ||
nil | ||
integer | direction | direction in which the equipment is cycled through |
3131 | function Player:onInputCycleHandTool(_, direction) |
3132 | if self.playerStateMachine:isAvailable("cycleHandtool") then |
3133 | local cycleHandtoolState = self.playerStateMachine:getState("cycleHandtool") |
3134 | cycleHandtoolState.cycleDirection = direction |
3135 | self.playerStateMachine:activateState("cycleHandtool") |
3136 | end |
3137 | end |
onInputDebugFlyToggle
DescriptionEvent function for the debug flying toggle.Definition
onInputDebugFlyToggle()Code
3149 | function Player:onInputDebugFlyToggle() |
3150 | if not self.walkingIsDisabled then |
3151 | if self.debugFlightCoolDown <= 0 then |
3152 | if g_flightModeEnabled then |
3153 | self.debugFlightMode = not self.debugFlightMode |
3154 | self.debugFlightCoolDown = 10 |
3155 | end |
3156 | end |
3157 | end |
3158 | end |
onInputDebugFlyUpDown
DescriptionEvent function for the debug flying vertical movement.Definition
onInputDebugFlyUpDown(nil, float inputValue)Arguments
nil | ||
float | inputValue |
3164 | function Player:onInputDebugFlyUpDown(_, inputValue) |
3165 | if not self.walkingIsDisabled then |
3166 | local move = inputValue * 0.25 * self.debugFlightModeWalkingSpeed * self.debugFlightModeRunningFactor |
3167 | self.inputInformation.moveUp = self.inputInformation.moveUp + move |
3168 | end |
3169 | end |
onInputEnter
DescriptionEvent function for enterDefinition
onInputEnter(nil, float inputValue)Arguments
nil | ||
float | inputValue |
3175 | function Player:onInputEnter(_, inputValue) |
3176 | if g_time > g_currentMission.lastInteractionTime + 200 then |
3177 | if g_currentMission.interactiveVehicleInRange and g_currentMission.accessHandler:canFarmAccess(self.farmId, g_currentMission.interactiveVehicleInRange) then |
3178 | g_currentMission.interactiveVehicleInRange:interact() |
3179 | elseif self.canRideAnimal then |
3180 | self.playerStateMachine:activateState("animalRide") |
3181 | end |
3182 | end |
3183 | end |
onInputInteract
DescriptionEvent function for interacting with an animalDefinition
onInputInteract()Code
3094 | function Player:onInputInteract(_, inputValue) |
3095 | -- Note: we need to store pressed state for animal cleaning (see PlayerStateAnimalInteract) which is a continuous |
3096 | -- action. Therefore, this event is called onUp and onDown. When the down event is received, input will be non-zero. |
3097 | if self.inputInformation.interactState ~= Player.BUTTONSTATES.PRESSED and inputValue ~= 0 then |
3098 | if self.playerStateMachine:isAvailable("drop") then |
3099 | self.playerStateMachine:activateState("drop") |
3100 | elseif self.playerStateMachine:isAvailable("pickup") then |
3101 | self.playerStateMachine:activateState("pickup") |
3102 | elseif self.playerStateMachine:isAvailable("animalInteract") then |
3103 | self.playerStateMachine:activateState("animalInteract") |
3104 | end |
3105 | |
3106 | self.inputInformation.interactState = Player.BUTTONSTATES.PRESSED |
3107 | else |
3108 | self.inputInformation.interactState = Player.BUTTONSTATES.RELEASED |
3109 | end |
3110 | end |
onInputJump
DescriptionEvent function for jumping.Definition
onInputJump()Code
3086 | function Player:onInputJump(_, inputValue) |
3087 | if self.playerStateMachine:isAvailable("jump") then |
3088 | self.playerStateMachine:activateState("jump") |
3089 | end |
3090 | end |
onInputLookLeftRight
DescriptionEvent function for player camera horizontal axis.Definition
onInputLookLeftRight(nil, float inputValue)Arguments
nil | ||
float | inputValue |
2956 | function Player:onInputLookLeftRight(_, inputValue, _, _, isMouse) |
2957 | if not self.lockedInput then |
2958 | if isMouse then |
2959 | inputValue = inputValue * 0.001 * 16.666 |
2960 | else |
2961 | inputValue = inputValue * g_currentDt *0.001 |
2962 | end |
2963 | self.inputInformation.yawCamera = self.inputInformation.yawCamera + inputValue |
2964 | end |
2965 | self.inputInformation.isMouseRotation = isMouse |
2966 | end |
onInputLookUpDown
DescriptionEvent function for player camera vertical axis.Definition
onInputLookUpDown(nil, float inputValue)Arguments
nil | ||
float | inputValue |
2981 | function Player:onInputLookUpDown(_, inputValue, _, _, isMouse) |
2982 | if not self.lockedInput then |
2983 | local pitchValue = g_gameSettings:getValue("invertYLook") and -inputValue or inputValue |
2984 | if isMouse then |
2985 | pitchValue = pitchValue * 0.001 * 16.666 |
2986 | else |
2987 | pitchValue = pitchValue * g_currentDt *0.001 |
2988 | end |
2989 | self.inputInformation.pitchCamera = self.inputInformation.pitchCamera + pitchValue |
2990 | end |
2991 | end |
onInputMoveForward
DescriptionEvent function for player forward/backward movement.Definition
onInputMoveForward(nil, float inputValue)Arguments
nil | ||
float | inputValue |
3007 | function Player:onInputMoveForward(_, inputValue) |
3008 | if not self.lockedInput then |
3009 | self.inputInformation.moveForward = self.inputInformation.moveForward + inputValue |
3010 | end |
3011 | end |
onInputMoveSide
DescriptionEvent function for player strafe movement.Definition
onInputMoveSide(nil, float inputValue)Arguments
nil | ||
float | inputValue |
2997 | function Player:onInputMoveSide(_, inputValue) |
2998 | if not self.lockedInput then |
2999 | self.inputInformation.moveRight = self.inputInformation.moveRight + inputValue |
3000 | end |
3001 | end |
onInputRotateObjectHorizontally
DescriptionEvent function for rotating object.Definition
onInputRotateObjectHorizontally()Code
3041 | function Player:onInputRotateObjectHorizontally(_, inputValue) |
3042 | if self.pickedUpObjectJointId ~= nil and math.abs(inputValue) > 0 then |
3043 | self:rotateObject(inputValue, 0.0, 1.0, 0.0) |
3044 | elseif self.isCarryingObject and self.isClient and self.isControlled then |
3045 | if inputValue ~= 0.0 then |
3046 | self.networkInformation.rotateObject = true |
3047 | else |
3048 | self.networkInformation.rotateObject = false |
3049 | end |
3050 | self.networkInformation.rotateObjectInputH = inputValue |
3051 | end |
3052 | end |
onInputRotateObjectVertically
DescriptionEvent function for rotating object.Definition
onInputRotateObjectVertically()Code
3056 | function Player:onInputRotateObjectVertically(_, inputValue) |
3057 | if self.pickedUpObjectJointId ~= nil and math.abs(inputValue) > 0 then |
3058 | self:rotateObject(inputValue, 1.0, 0.0, 0.0) |
3059 | elseif self.isCarryingObject and self.isClient and self.isControlled then |
3060 | if inputValue ~= 0.0 then |
3061 | self.networkInformation.rotateObject = true |
3062 | else |
3063 | self.networkInformation.rotateObject = false |
3064 | end |
3065 | self.networkInformation.rotateObjectInputV = inputValue |
3066 | end |
3067 | end |
onInputRun
DescriptionEvent function for player running.Definition
onInputRun(nil, float inputValue)Arguments
nil | ||
float | inputValue |
3017 | function Player:onInputRun(_, inputValue) |
3018 | self.inputInformation.runAxis = inputValue |
3019 | |
3020 | if self.debugFlightMode then |
3021 | if inputValue > 0 and self.debugFlightModeRunningFactor ~= 4.0 then |
3022 | self.debugFlightModeRunningFactor = 4.0 |
3023 | elseif inputValue == 0 and self.debugFlightModeRunningFactor ~= 1.0 then |
3024 | self.debugFlightModeRunningFactor = 1.0 |
3025 | end |
3026 | end |
3027 | end |
onInputThrowObject
DescriptionEvent function for throwing an object.Definition
onInputThrowObject()Code
3141 | function Player:onInputThrowObject(_, inputValue) |
3142 | if self.playerStateMachine:isAvailable("throw") then |
3143 | self.playerStateMachine:activateState("throw") |
3144 | end |
3145 | end |
onInputToggleLight
DescriptionEvent function for flashlight toggle.Definition
onInputToggleLight()Code
3120 | function Player:onInputToggleLight() |
3121 | if self.playerStateMachine:isAvailable("useLight") then |
3122 | self.playerStateMachine:activateState("useLight") |
3123 | end |
3124 | end |
onLeave
DescriptionCalled when player Leaves mission. Update traffic system to ignore this player. Clear position history, visibility. Removes tools. Deregister from companion animal system. Moves to (0, -200, 0)Definition
onLeave()Code
1544 | function Player:onLeave() |
1545 | if self.isControlled then |
1546 | g_messageCenter:publish(MessageType.OWN_PLAYER_LEFT) |
1547 | g_messageCenter:unsubscribe(MessageType.INPUT_BINDINGS_CHANGED, self) |
1548 | end |
1549 | |
1550 | g_currentMission:removeMapHotspot(self.playerHotspot) |
1551 | |
1552 | -- stop swim sound |
1553 | g_soundManager:stopSamples(self.model.soundInformation.samples) |
1554 | |
1555 | self:removeActionEvents() |
1556 | |
1557 | if self.foliageBendingId ~= nil then |
1558 | g_currentMission.foliageBendingSystem:destroyObject(self.foliageBendingId) |
1559 | self.foliageBendingId = nil |
1560 | end |
1561 | |
1562 | if self.isServer then |
1563 | self:setOwner(nil) |
1564 | end |
1565 | if self.isEntered or self.isServer then |
1566 | self:raiseDirtyFlags(self.networkInformation.dirtyFlag) |
1567 | end |
1568 | if self.isServer and not self.isEntered and g_currentMission.trafficSystem ~= nil and g_currentMission.trafficSystem.trafficSystemId ~= 0 then |
1569 | removeTrafficSystemPlayer(g_currentMission.trafficSystem.trafficSystemId, self.graphicsRootNode) |
1570 | end |
1571 | |
1572 | g_currentMission:addPauseListeners(self) |
1573 | |
1574 | --clear history |
1575 | self.networkInformation.history = {} |
1576 | self.isControlled = false |
1577 | self.isEntered = false |
1578 | self:setVisibility(false) |
1579 | |
1580 | if self:hasHandtoolEquipped() then |
1581 | self.baseInformation.currentHandtool:onDeactivate() |
1582 | self.baseInformation.currentHandtool:delete() |
1583 | self.baseInformation.currentHandtool = nil |
1584 | end |
1585 | local dogHouse = g_currentMission:getDoghouse(self.farmId) |
1586 | if dogHouse ~= nil and dogHouse.dog ~= nil then |
1587 | dogHouse.dog:onPlayerLeave(self) |
1588 | end |
1589 | |
1590 | self.model:enableTorch(false) |
1591 | self:moveToAbsoluteInternal(0, -200, 0) |
1592 | end |
onLeaveVehicle
DescriptionCalled when player leaves vehicleDefinition
onLeaveVehicle()Code
1537 | function Player:onLeaveVehicle() |
1538 | self.playerStateMachine:deactivateState("animalRide") |
1539 | self.playerStateMachine:deactivateState("jump") |
1540 | end |
onPickedUpObjectJointBreak
DescriptionCallback when picked-up object's joint is brokenDefinition
onPickedUpObjectJointBreak(integer jointIndex, float breakingImpulse)Arguments
integer | jointIndex | index of the joint |
float | breakingImpulse |
always | returns | false |
2343 | function Player:onPickedUpObjectJointBreak(jointIndex, breakingImpulse) |
2344 | if jointIndex == self.pickedUpObjectJointId then |
2345 | self:pickUpObject(false) |
2346 | end |
2347 | -- Do not delete the joint internally, we already deleted it |
2348 | return false |
2349 | end |
pickUpObject
DescriptionPicks up an object and links it via a spring mechanism.Definition
pickUpObject(bool state, bool noEventSend)Arguments
bool | state | if true will join the object, else the joint is removed |
bool | noEventSend | unused parameter |
2189 | function Player:pickUpObject(state, noEventSend) |
2190 | PlayerPickUpObjectEvent.sendEvent(self, state, noEventSend) |
2191 | |
2192 | if self.isServer then |
2193 | if state and (self.isObjectInRange and self.lastFoundObject ~= nil and entityExists(self.lastFoundObject)) and not self.isCarryingObject then |
2194 | local constr = JointConstructor.new() |
2195 | |
2196 | -- disable collision with CCT |
2197 | self.pickedUpObjectCollisionMask = getCollisionMask(self.lastFoundObject) |
2198 | local newPickedUpObjectCollisionFlag = bitXOR(bitAND(self.pickedUpObjectCollisionMask, self.cctMovementCollisionMask), self.pickedUpObjectCollisionMask) |
2199 | setCollisionMask(self.lastFoundObject, newPickedUpObjectCollisionFlag) |
2200 | |
2201 | local kinematicHelperNode, kinematicHelperNodeChild = self.model:getKinematicHelpers() |
2202 | constr:setActors(kinematicHelperNode, self.lastFoundObject) |
2203 | |
2204 | for i=0, 2 do |
2205 | constr:setRotationLimit(i, 0, 0) |
2206 | constr:setTranslationLimit(i, true, 0, 0) |
2207 | end |
2208 | |
2209 | -- set position of joint to center of the object |
2210 | local mx, my, mz = getCenterOfMass(self.lastFoundObject) |
2211 | local wx, wy, wz = localToWorld(self.lastFoundObject, mx, my, mz) |
2212 | constr:setJointWorldPositions(wx, wy, wz, wx, wy, wz) |
2213 | |
2214 | local nx, ny, nz = localDirectionToWorld(self.lastFoundObject, 1, 0, 0) |
2215 | constr:setJointWorldAxes(nx, ny, nz, nx, ny, nz) |
2216 | |
2217 | local yx, yy, yz = localDirectionToWorld(self.lastFoundObject, 0, 1, 0) |
2218 | constr:setJointWorldNormals(yx, yy, yz, yx, yy, yz) |
2219 | constr:setEnableCollision(false) |
2220 | |
2221 | -- Update child, used for object rotation by player |
2222 | setWorldTranslation(kinematicHelperNodeChild, wx, wy, wz) |
2223 | setWorldRotation(kinematicHelperNodeChild, getWorldRotation(self.lastFoundObject)) |
2224 | |
2225 | -- set spring/damper ?! |
2226 | local dampingRatio = 1.0 |
2227 | local mass = getMass(self.lastFoundObject) |
2228 | |
2229 | local rotationLimitSpring = {} |
2230 | local rotationLimitDamper = {} |
2231 | for i=1, 3 do |
2232 | rotationLimitSpring[i] = mass * 60 |
2233 | rotationLimitDamper[i] = dampingRatio * 2 * math.sqrt( mass * rotationLimitSpring[i] ) |
2234 | --print(" rotSpring/Damper = "..tostring(rotationLimitSpring[i]).." / "..tostring(rotationLimitDamper[i])) |
2235 | end |
2236 | constr:setRotationLimitSpring(rotationLimitSpring[1], rotationLimitDamper[1], rotationLimitSpring[2], rotationLimitDamper[2], rotationLimitSpring[3], rotationLimitDamper[3]) |
2237 | |
2238 | local translationLimitSpring = {} |
2239 | local translationLimitDamper = {} |
2240 | for i=1, 3 do |
2241 | translationLimitSpring[i] = mass * 60 |
2242 | translationLimitDamper[i] = dampingRatio * 2 * math.sqrt( mass * translationLimitSpring[i] ) |
2243 | --print(" transSpring/Damper = "..tostring(translationLimitSpring[i]).." / "..tostring(translationLimitDamper[i])) |
2244 | end |
2245 | constr:setTranslationLimitSpring(translationLimitSpring[1], translationLimitDamper[1], translationLimitSpring[2], translationLimitDamper[2], translationLimitSpring[3], translationLimitDamper[3]) |
2246 | |
2247 | local forceAcceleration = 4 |
2248 | local forceLimit = forceAcceleration * mass * 40.0 |
2249 | constr:setBreakable(forceLimit, forceLimit) |
2250 | |
2251 | self.pickedUpObjectJointId = constr:finalize() |
2252 | |
2253 | addJointBreakReport(self.pickedUpObjectJointId, "onPickedUpObjectJointBreak", self) |
2254 | |
2255 | self.pickedUpObject = self.lastFoundObject |
2256 | self.isCarryingObject = true |
2257 | Player.PICKED_UP_OBJECTS[self.pickedUpObject] = true |
2258 | |
2259 | local object = g_currentMission:getNodeObject(self.pickedUpObject) |
2260 | if object ~= nil then |
2261 | object.thrownFromPosition = nil |
2262 | end |
2263 | else |
2264 | if self.pickedUpObjectJointId ~= nil then |
2265 | removeJoint(self.pickedUpObjectJointId) |
2266 | self.pickedUpObjectJointId = nil |
2267 | self.isCarryingObject = false |
2268 | Player.PICKED_UP_OBJECTS[self.pickedUpObject] = false |
2269 | |
2270 | if entityExists(self.pickedUpObject) then |
2271 | local vx, vy, vz = getLinearVelocity(self.pickedUpObject) |
2272 | if vx ~= nil then -- in case the object has switched from dynamic to kinematic |
2273 | vx = MathUtil.clamp(vx, -5, 5) |
2274 | vy = MathUtil.clamp(vy, -5, 5) |
2275 | vz = MathUtil.clamp(vz, -5, 5) |
2276 | setLinearVelocity(self.pickedUpObject, vx, vy, vz) |
2277 | end |
2278 | -- setAngularVelocity(self.pickedUpObject, vx, vy, vz) |
2279 | setCollisionMask(self.pickedUpObject, self.pickedUpObjectCollisionMask) |
2280 | self.pickedUpObjectCollisionMask = 0 |
2281 | end |
2282 | |
2283 | local object = g_currentMission:getNodeObject(self.pickedUpObject) |
2284 | if object ~= nil then |
2285 | object.thrownFromPosition = nil |
2286 | end |
2287 | self.pickedUpObject = nil |
2288 | end |
2289 | end |
2290 | end |
2291 | end |
pickUpObjectRaycastCallback
DescriptionCallback used when raycast hists an object. Updates player information so it can be used to pickup the object.Definition
pickUpObjectRaycastCallback(integer hitObjectId, float x, float y, float z, float distance)Arguments
integer | hitObjectId | scenegraph object id |
float | x | world x hit position |
float | y | world y hit position |
float | z | world z hit position |
float | distance | distance at which the cast hit the object |
bool | returns | true object that was hit is valid |
2126 | function Player:pickUpObjectRaycastCallback(hitObjectId, x, y, z, distance) |
2127 | if hitObjectId ~= g_currentMission.terrainRootNode and Player.PICKED_UP_OBJECTS[hitObjectId] ~= true then |
2128 | |
2129 | --#debug if self.pickupRaycastDebugEnabled then |
2130 | --#debug renderText(0.010, 0.55, 0.02, "Player raycast callback") |
2131 | --#debug local colMaskDec = getCollisionMask(hitObjectId) |
2132 | --#debug local text = string.format("nodeId=%s (%s), maskHex=%x, maskDec=%s, hasTrigger=%s", hitObjectId, getName(hitObjectId), colMaskDec, colMaskDec, getHasTrigger(hitObjectId)) |
2133 | --#debug renderText(0.010, 0.53 - self.raycastCallbackIndex * 0.02, 0.016, text) |
2134 | --#debug self.raycastCallbackIndex = self.raycastCallbackIndex + 1 |
2135 | --#debug end |
2136 | |
2137 | local rigidBodyType = getRigidBodyType(hitObjectId) |
2138 | if rigidBodyType == RigidBodyType.DYNAMIC or rigidBodyType == RigidBodyType.KINEMATIC then |
2139 | -- Store any object we hit, even it if cannot be picked up. |
2140 | -- This is used for the info HUD |
2141 | self.lastFoundAnyObject = hitObjectId |
2142 | |
2143 | if not self.isServer then |
2144 | -- only consider first potentially valid object |
2145 | return false |
2146 | end |
2147 | end |
2148 | |
2149 | if self.isServer and rigidBodyType == RigidBodyType.DYNAMIC then |
2150 | -- check if mounted: |
2151 | local canBePickedUp = true |
2152 | local object = g_currentMission:getNodeObject(hitObjectId) |
2153 | if object ~= nil then |
2154 | if object.dynamicMountObject ~= nil or object.tensionMountObject ~= nil then |
2155 | canBePickedUp = false |
2156 | end |
2157 | if object.getCanBePickedUp ~= nil then |
2158 | if not object:getCanBePickedUp(self) and not self.superStrengthEnabled then |
2159 | canBePickedUp = false |
2160 | end |
2161 | end |
2162 | end |
2163 | |
2164 | if canBePickedUp then |
2165 | local mass |
2166 | if object ~= nil and object.getTotalMass ~= nil then |
2167 | mass = object:getTotalMass() |
2168 | else |
2169 | mass = getMass(hitObjectId) |
2170 | end |
2171 | |
2172 | self.lastFoundObject = hitObjectId |
2173 | self.lastFoundObjectMass = mass |
2174 | self.lastFoundObjectHitPoint = {x, y, z} |
2175 | end |
2176 | |
2177 | -- only consider first potentially valid object |
2178 | return false |
2179 | end |
2180 | end |
2181 | |
2182 | return true |
2183 | end |
readStream
DescriptionReads from network streamDefinition
readStream(integer streamId, table connection)Arguments
integer | streamId | id of the stream to read |
table | connection | connection information |
458 | function Player:readStream(streamId, connection, objectId) |
459 | Player:superClass().readStream(self, streamId, connection) |
460 | |
461 | local isOwner = streamReadBool(streamId) |
462 | |
463 | local x = streamReadFloat32(streamId) |
464 | local y = streamReadFloat32(streamId) |
465 | local z = streamReadFloat32(streamId) |
466 | |
467 | local isControlled = streamReadBool(streamId) |
468 | |
469 | self.farmId = streamReadUIntN(streamId, FarmManager.FARM_ID_SEND_NUM_BITS) |
470 | self.userId = NetworkUtil.readNodeObjectId(streamId) |
471 | |
472 | self:load(connection, isOwner) |
473 | |
474 | self:moveToAbsoluteInternal(x, y, z) |
475 | self:setLightIsActive(streamReadBool(streamId), true) |
476 | |
477 | if isControlled ~= self.isControlled then |
478 | if isControlled then |
479 | self:onEnter(false) |
480 | else |
481 | self:onLeave() |
482 | end |
483 | end |
484 | |
485 | local hasHandtool = streamReadBool(streamId) |
486 | if hasHandtool then |
487 | local handtoolFilename = NetworkUtil.convertFromNetworkFilename(streamReadString(streamId)) |
488 | self:equipHandtool(handtoolFilename, true, true) |
489 | end |
490 | |
491 | -- The object has been received. Request any style info from the server |
492 | g_client:getServerConnection():sendEvent(PlayerRequestStyleEvent.new(objectId)) |
493 | end |
readUpdateStream
DescriptionReads from network stream via updateDefinition
readUpdateStream(integer streamId, integer timestamp, table connection)Arguments
integer | streamId | id of the stream to read |
integer | timestamp | timestamp of the packet |
table | connection | connection information |
528 | function Player:readUpdateStream(streamId, timestamp, connection) |
529 | if connection:getIsServer() then |
530 | -- client code (read data from server) |
531 | -- TODO look into Vehicle:readUpdateStream NetworkUtil.readCompressedWorldPosition and NetworkUtil.readCompressedAngle |
532 | local x = streamReadFloat32(streamId) |
533 | local y = streamReadFloat32(streamId) |
534 | local z = streamReadFloat32(streamId) |
535 | local alpha = streamReadFloat32(streamId) |
536 | self.cameraRotY = alpha |
537 | |
538 | self.isObjectInRange = streamReadBool(streamId) |
539 | if self.isObjectInRange then |
540 | -- TODO: compress |
541 | self.lastFoundObjectMass = streamReadFloat32(streamId) |
542 | else |
543 | self.lastFoundObjectMass = nil |
544 | end |
545 | self.isCarryingObject = streamReadBool(streamId) |
546 | local isOnGround = streamReadBool(streamId) |
547 | |
548 | if self.isOwner then |
549 | local index = streamReadInt32(streamId) |
550 | --print("CLIENT ( "..tostring(self).." ): x/y/z = "..tostring(x).." / "..tostring(y).." / "..tostring(z)) |
551 | -- remove history entries before the one sent by the server |
552 | while self.networkInformation.history[1] ~= nil and self.networkInformation.history[1].index <= index do |
553 | table.remove(self.networkInformation.history, 1) |
554 | end |
555 | -- set position sent by server |
556 | setCCTPosition(self.controllerIndex, x, y, z) |
557 | -- move cct from the rest of the history queue |
558 | -- Accumulate moves from multiple history entries so that we never apply more than 5 moveCCT's |
559 | local history = self.networkInformation.history |
560 | local numHistory = #history |
561 | if numHistory <= 5 then |
562 | for i=1,numHistory do |
563 | moveCCT(self.controllerIndex, history[i].movementX, history[i].movementY, history[i].movementZ, self.cctMovementCollisionMask) |
564 | end |
565 | else |
566 | -- Accumulate moves with different amounts so that we achieve exactly the correct historty |
567 | -- Some will use floored, some will use floored + 1 |
568 | -- Use the smaller amount for the older moves as errors for older moves potentially leads to larger errors now than for more recent ones |
569 | local accumSizeSmall = math.floor(numHistory / 5) |
570 | local numSmall = 5 - numHistory + accumSizeSmall * 5 |
571 | local startI = 1 |
572 | for i=1,5 do |
573 | local endI |
574 | if i <= numSmall then |
575 | endI = startI+accumSizeSmall-1 |
576 | else |
577 | endI = startI+accumSizeSmall |
578 | end |
579 | local movementX, movementY, movementZ = 0,0,0 |
580 | for j=startI,endI do |
581 | movementX = movementX + history[j].movementX |
582 | movementY = movementY + history[j].movementY |
583 | movementZ = movementZ + history[j].movementZ |
584 | end |
585 | moveCCT(self.controllerIndex, movementX, movementY, movementZ, self.cctMovementCollisionMask) |
586 | startI = endI+1 |
587 | end |
588 | end |
589 | -- set target physics index to current index |
590 | self.networkInformation.updateTargetTranslationPhysicsIndex = getPhysicsUpdateIndex() -- update until the current physics index is simulated |
591 | -- [animation] |
592 | self.baseInformation.isCrouched = streamReadBool(streamId) |
593 | -- |
594 | else |
595 | local isControlled = streamReadBool(streamId) |
596 | if isControlled ~= self.isControlled then |
597 | self:moveToAbsoluteInternal(x, y, z) |
598 | if isControlled then |
599 | self:onEnter(false) |
600 | else |
601 | self:onLeave() |
602 | end |
603 | else |
604 | -- other clients: set position, refrain from using target index and start new network interpolation phase |
605 | setTranslation(self.rootNode, x, y, z) |
606 | self.networkInformation.interpolatorPosition:setTargetPosition(x, y, z) |
607 | if isOnGround then |
608 | self.networkInformation.interpolatorOnGround:setTargetValue(1.0) |
609 | else |
610 | self.networkInformation.interpolatorOnGround:setTargetValue(0.0) |
611 | end |
612 | self.networkInformation.updateTargetTranslationPhysicsIndex = -1 |
613 | self.networkInformation.interpolationTime:startNewPhaseNetwork() |
614 | -- force update |
615 | self:raiseActive() |
616 | end |
617 | -- [animation] |
618 | self.baseInformation.isCrouched = streamReadBool(streamId) |
619 | -- |
620 | end |
621 | else |
622 | -- server code (read data from client) |
623 | if connection == self.networkInformation.creatorConnection then |
624 | -- we received translation information from client and we ask the physics to move the avatar; we insert the current physics index in the history queue and force an update() |
625 | local movementX=streamReadFloat32(streamId) |
626 | local movementY=streamReadFloat32(streamId) |
627 | local movementZ=streamReadFloat32(streamId) |
628 | |
629 | local qx = streamReadFloat32(streamId) |
630 | local qy = streamReadFloat32(streamId) |
631 | local qz = streamReadFloat32(streamId) |
632 | local qw = streamReadFloat32(streamId) |
633 | |
634 | local index = streamReadInt32(streamId) |
635 | local isControlled = streamReadBool(streamId) |
636 | |
637 | moveCCT(self.controllerIndex, movementX, movementY, movementZ, self.cctMovementCollisionMask) |
638 | |
639 | self.networkInformation.interpolationTime:startNewPhaseNetwork() |
640 | self.networkInformation.interpolatorQuaternion:setTargetQuaternion(qx, qy, qz, qw) |
641 | local physicsIndex = getPhysicsUpdateIndex() |
642 | table.insert(self.networkInformation.history, {index=index, physicsIndex = physicsIndex}) |
643 | |
644 | self.networkInformation.updateTargetTranslationPhysicsIndex = physicsIndex -- update until the current physics index is simulated |
645 | |
646 | self:raiseActive() |
647 | if isControlled ~= self.isControlled then |
648 | if isControlled then |
649 | self:onEnter(false) |
650 | else |
651 | self:onLeave() |
652 | end |
653 | end |
654 | -- [animation] |
655 | self.baseInformation.isCrouched = streamReadBool(streamId) |
656 | -- |
657 | if self.isCarryingObject then |
658 | self.networkInformation.rotateObject = streamReadBool(streamId) |
659 | if self.networkInformation.rotateObject then |
660 | self.networkInformation.rotateObjectInputH = streamReadFloat32(streamId) |
661 | self.networkInformation.rotateObjectInputV = streamReadFloat32(streamId) |
662 | end |
663 | end |
664 | end |
665 | end |
666 | end |
recordPositionInformation
DescriptionDefinitionrecordPositionInformation()Code
2596 | function Player:recordPositionInformation() |
2597 | local currentPositionX, _, currentPositionZ = getTranslation(self.graphicsRootNode) |
2598 | local deltaPosX = currentPositionX - self.baseInformation.lastPositionX |
2599 | local deltaPosZ = currentPositionZ - self.baseInformation.lastPositionZ |
2600 | self.baseInformation.lastPositionX = currentPositionX |
2601 | self.baseInformation.lastPositionZ = currentPositionZ |
2602 | |
2603 | local groundDistanceCovered = MathUtil.vector2Length(deltaPosX, deltaPosZ) |
2604 | self.motionInformation.justMoved = groundDistanceCovered > 0.0 |
2605 | |
2606 | if self.baseInformation.isOnGround then |
2607 | self.motionInformation.currentCoveredGroundDistance = groundDistanceCovered |
2608 | self.motionInformation.coveredGroundDistance = self.motionInformation.coveredGroundDistance + groundDistanceCovered |
2609 | end |
2610 | end |
registerActionEvents
DescriptionRegister required player action events.Definition
registerActionEvents()Code
2877 | function Player:registerActionEvents() |
2878 | -- register action events for the player context without switching (important when this is called from within the UI context) |
2879 | g_inputBinding:beginActionEventsModification(Player.INPUT_CONTEXT_NAME) |
2880 | |
2881 | for actionId, inputRegisterEntry in pairs(self.inputInformation.registrationList) do |
2882 | local _ |
2883 | local startActive = false |
2884 | |
2885 | if inputRegisterEntry.activeType == Player.INPUT_ACTIVE_TYPE.STARTS_ENABLED then |
2886 | startActive = true |
2887 | elseif inputRegisterEntry.activeType == Player.INPUT_ACTIVE_TYPE.STARTS_DISABLED then |
2888 | startActive = false |
2889 | elseif inputRegisterEntry.activeType == Player.INPUT_ACTIVE_TYPE.IS_MOVEMENT then |
2890 | startActive = not self.walkingIsLocked |
2891 | elseif inputRegisterEntry.activeType == Player.INPUT_ACTIVE_TYPE.IS_CARRYING then |
2892 | startActive = self.isCarryingObject |
2893 | elseif inputRegisterEntry.activeType == Player.INPUT_ACTIVE_TYPE.IS_DEBUG then |
2894 | startActive = self.baseInformation.isInDebug |
2895 | end |
2896 | |
2897 | -- register with conflict removal flag, will disable conflicting bindings of newly registered actions |
2898 | _, inputRegisterEntry.eventId = g_inputBinding:registerActionEvent(actionId, self, inputRegisterEntry.callback, inputRegisterEntry.triggerUp, inputRegisterEntry.triggerDown, inputRegisterEntry.triggerAlways, startActive, inputRegisterEntry.callbackState, true) |
2899 | if inputRegisterEntry.text ~= nil and inputRegisterEntry.text ~= "" then |
2900 | g_inputBinding:setActionEventText(inputRegisterEntry.eventId, inputRegisterEntry.text) |
2901 | end |
2902 | |
2903 | g_inputBinding:setActionEventTextVisibility(inputRegisterEntry.eventId, inputRegisterEntry.textVisibility) |
2904 | end |
2905 | |
2906 | if g_touchHandler ~= nil then |
2907 | if not self.walkingIsLocked then |
2908 | self.touchListenerY = g_touchHandler:registerGestureListener(TouchHandler.GESTURE_AXIS_Y, Player.touchEventLookUpDown, self) |
2909 | self.touchListenerX = g_touchHandler:registerGestureListener(TouchHandler.GESTURE_AXIS_X, Player.touchEventLookLeftRight, self) |
2910 | else |
2911 | g_touchHandler:removeGestureListener(self.touchListenerY) |
2912 | g_touchHandler:removeGestureListener(self.touchListenerX) |
2913 | end |
2914 | end |
2915 | |
2916 | -- reset registration context, update event data in input system: |
2917 | g_inputBinding:endActionEventsModification() |
2918 | |
2919 | if self.isEntered then |
2920 | g_currentMission.activatableObjectsSystem:activate(Player.INPUT_CONTEXT_NAME) |
2921 | end |
2922 | end |
removeActionEvents
DescriptionRemove all player action events.Definition
removeActionEvents()Code
2926 | function Player:removeActionEvents() |
2927 | -- reset previously disabled bindings' enabled state |
2928 | g_inputBinding:resetActiveActionBindings() |
2929 | |
2930 | -- modify action events in player context without switching (important because this can be called from within the UI) |
2931 | g_inputBinding:beginActionEventsModification(Player.INPUT_CONTEXT_NAME) |
2932 | g_inputBinding:removeActionEventsByTarget(self) |
2933 | for _, inputRegisterEntry in pairs(self.inputInformation.registrationList) do |
2934 | inputRegisterEntry.eventId = "" |
2935 | end |
2936 | g_inputBinding:endActionEventsModification() |
2937 | |
2938 | if self.isEntered then |
2939 | g_currentMission.activatableObjectsSystem:deactivate(Player.INPUT_CONTEXT_NAME) |
2940 | end |
2941 | end |
resetBrake
DescriptionDefinitionresetBrake()Code
2627 | function Player:resetBrake() |
2628 | self:setVelocityToMotion(0.0, 0.0, 0.0) |
2629 | self:setAccelerationToMotion(0.0, 0.0, 0.0) |
2630 | self.motionInformation.brakeForce = {0.0, 0.0, 0.0} |
2631 | self.motionInformation.isBraking = false |
2632 | end |
resetCameraInputsInformation
DescriptionReset for input managed in update() methodDefinition
resetCameraInputsInformation()Code
2513 | function Player:resetCameraInputsInformation() |
2514 | self.inputInformation.pitchCamera = 0 |
2515 | self.inputInformation.yawCamera = 0 |
2516 | self.inputInformation.crouchState = Player.BUTTONSTATES.RELEASED |
2517 | end |
resetInputsInformation
DescriptionReset input information inbetween frames. Input is accumulated by events until read, processed and reset. Reset for input managed in updateTick() methodDefinition
resetInputsInformation()Code
2504 | function Player:resetInputsInformation() |
2505 | self.inputInformation.moveRight = 0 |
2506 | self.inputInformation.moveForward = 0 |
2507 | self.inputInformation.moveUp = 0 |
2508 | self.inputInformation.runAxis = 0 |
2509 | end |
rotateObject
DescriptionRotates objectDefinition
rotateObject()Code
3071 | function Player:rotateObject(inputValue, axisX, axisY, axisZ) |
3072 | local jointIndex = self.pickedUpObjectJointId |
3073 | local actor = 0 |
3074 | |
3075 | local _, objectTransform = self.model:getKinematicHelpers() |
3076 | local rotX, rotY, rotZ = localDirectionToLocal(self.cameraNode, objectTransform, axisX, axisY, axisZ) |
3077 | local dtInSec = g_physicsDt * 0.001 |
3078 | local rotation = math.rad(90.0) * dtInSec * inputValue |
3079 | |
3080 | rotateAboutLocalAxis(objectTransform, rotation, rotX, rotY, rotZ) |
3081 | setJointFrame(jointIndex, actor, objectTransform) |
3082 | end |
setCustomWorkStylePreset
DescriptionSets a custom work style presetDefinition
setCustomWorkStylePreset()Code
1876 | function Player:setCustomWorkStylePreset(presetName) |
1877 | if self.isDeleting then |
1878 | return |
1879 | end |
1880 | |
1881 | self.model:applyCustomWorkStyle(presetName) |
1882 | end |
setCuttingAnim
DescriptionSet cutting animationDefinition
setCuttingAnim(bool isCutting, bool isHorizontalCut)Arguments
bool | isCutting | true if player is cutting |
bool | isHorizontalCut | true if player is cutting horizontaly |
439 | function Player:setCuttingAnim(isCutting, isHorizontalCut) |
440 | if not isCutting and (self.baseInformation.isUsingChainsawHorizontal or self.baseInformation.isUsingChainsawVertical) then |
441 | self.baseInformation.isUsingChainsawHorizontal = false |
442 | self.baseInformation.isUsingChainsawVertical = false |
443 | elseif isCutting then |
444 | if isHorizontalCut then |
445 | self.baseInformation.isUsingChainsawHorizontal = true |
446 | self.baseInformation.isUsingChainsawVertical = false |
447 | else |
448 | self.baseInformation.isUsingChainsawHorizontal = false |
449 | self.baseInformation.isUsingChainsawVertical = true |
450 | end |
451 | end |
452 | end |
setIKDirty
DescriptionSets all ik chain node to dirty so that they are recalculatedDefinition
setIKDirty()Code
1307 | function Player:setIKDirty() |
1308 | self.model:setIKDirty() |
1309 | end |
setInputState
DescriptionDisable given input actionDefinition
setInputState()Code
994 | function Player:setInputState(inputAction, state) |
995 | --#debug assertWithCallstack(inputAction ~= nil) |
996 | local id = self.inputInformation.registrationList[inputAction].eventId |
997 | g_inputBinding:setActionEventActive(id, state) |
998 | g_inputBinding:setActionEventTextVisibility(id, state) |
999 | self.inputInformation.registrationList[inputAction].lastState = state |
1000 | end |
setLightIsActive
DescriptionSet torch state. This is called by the player state machineDefinition
setLightIsActive()Code
1770 | function Player:setLightIsActive(isActive, noEventSend) |
1771 | if isActive ~= self.isTorchActive then |
1772 | self.isTorchActive = isActive |
1773 | PlayerToggleLightEvent.sendEvent(self, isActive, noEventSend) |
1774 | |
1775 | self.model:enableTorch(isActive, true) |
1776 | end |
1777 | end |
setRotation
DescriptionSet player rotationDefinition
setRotation(float rotX, float rotY)Arguments
float | rotX | set rotation x parameter; vertical X rotation is clamped |
float | rotY | set rotation y parameter (graphics node, target graphics and camera) |
1409 | function Player:setRotation(rotX, rotY) |
1410 | self.rotX = math.min(1.2, math.max(-1.5, rotX)) |
1411 | self.rotY = rotY |
1412 | |
1413 | self.graphicsRotY = rotY |
1414 | self.cameraRotY = rotY |
1415 | self.targetGraphicsRotY = rotY |
1416 | end |
setThirdPersonViewActive
DescriptionEnables or disables the third person viewDefinition
setThirdPersonViewActive(boolean isActive)Arguments
boolean | isActive | third person view is active |
2749 | function Player:setThirdPersonViewActive(isActive) |
2750 | self.thirdPersonViewActive = isActive |
2751 | |
2752 | self:updateCameraModelTarget() |
2753 | end |
setVisibility
DescriptionSets third person mesh visibilityDefinition
setVisibility(bool visibility)Arguments
bool | visibility | if true will update visibility accordingly. |
1597 | function Player:setVisibility(visibility) |
1598 | self.model:setVisibility(visibility) |
1599 | end |
setWalkingLock
DescriptionLock or unlock the player's movement. Sets the Player.walkingIsLocked flag and enables/disables movement action events accordingly.Definition
setWalkingLock(isLocked If)Arguments
isLocked | If | true, the player's movement is locked. Otherwise, it is released. |
2726 | function Player:setWalkingLock(isLocked) |
2727 | self.walkingIsLocked = isLocked |
2728 | |
2729 | for _, inputRegistration in pairs(self.inputInformation.registrationList) do |
2730 | if inputRegistration.activeType == Player.INPUT_ACTIVE_TYPE.IS_MOVEMENT then |
2731 | g_inputBinding:setActionEventActive(inputRegistration.eventId, not isLocked) |
2732 | end |
2733 | end |
2734 | |
2735 | if g_touchHandler ~= nil then |
2736 | if not isLocked then |
2737 | self.touchListenerY = g_touchHandler:registerGestureListener(TouchHandler.GESTURE_AXIS_Y, Player.touchEventLookUpDown, self) |
2738 | self.touchListenerX = g_touchHandler:registerGestureListener(TouchHandler.GESTURE_AXIS_X, Player.touchEventLookLeftRight, self) |
2739 | else |
2740 | g_touchHandler:removeGestureListener(self.touchListenerY) |
2741 | g_touchHandler:removeGestureListener(self.touchListenerX) |
2742 | end |
2743 | end |
2744 | end |
testScope
DescriptionCheck if a position is within clip distanceDefinition
testScope(float x, float y, float z, float coeff)Arguments
float | x | world x position |
float | y | world y position |
float | z | world z position |
float | coeff | parameter is unused |
bool | returns | true if distance to player root node is lower than clip distance |
1608 | function Player:testScope(x, y, z, coeff) |
1609 | local x1, y1, z1 = getTranslation(self.rootNode) |
1610 | local dist = MathUtil.vector3Length(x1 - x, y1 - y, z1 - z) |
1611 | local clipDist = self.clipDistance |
1612 | if dist < clipDist * clipDist then |
1613 | return true |
1614 | else |
1615 | return false |
1616 | end |
1617 | end |
throwObject
DescriptionThrows an object. Activates dog to fetch a ball if conditions are met.Definition
throwObject()Code
2295 | function Player:throwObject(noEventSend) |
2296 | PlayerThrowObjectEvent.sendEvent(self, noEventSend) |
2297 | if self.pickedUpObject ~= nil and self.pickedUpObjectJointId ~= nil then |
2298 | local pickedUpObject = self.pickedUpObject |
2299 | self:pickUpObject(false) |
2300 | |
2301 | local mass = getMass(pickedUpObject) |
2302 | |
2303 | local v = 8 * (1.1-mass/Player.MAX_PICKABLE_OBJECT_MASS) -- speed between 0.8 and 8.8 based on mass of current object |
2304 | local vx, vy, vz = localDirectionToWorld(self.cameraNode, 0, 0, -v) |
2305 | setLinearVelocity(pickedUpObject, vx, vy, vz) |
2306 | |
2307 | local object = g_currentMission:getNodeObject(pickedUpObject) |
2308 | if object ~= nil then |
2309 | object.thrownFromPosition = {getWorldTranslation(self.rootNode)} |
2310 | |
2311 | if object:isa(DogBall) then |
2312 | local dogHouse = g_currentMission:getDoghouse(self.farmId) |
2313 | if dogHouse ~= nil then |
2314 | local dog = dogHouse:getDog() |
2315 | if dog ~= nil then |
2316 | local px,py,pz = getWorldTranslation(self.rootNode) |
2317 | local distance, _ = getCompanionClosestDistance(dog.dogInstance, px, py, pz) |
2318 | if distance < 10.0 then |
2319 | dog:fetchItem(self, object) |
2320 | end |
2321 | end |
2322 | end |
2323 | end |
2324 | end |
2325 | elseif (self.isObjectInRange and self.lastFoundObject ~= nil) and not self.isCarryingObject then |
2326 | local mass = getMass(self.lastFoundObject) |
2327 | |
2328 | if mass <= Player.MAX_PICKABLE_OBJECT_MASS then |
2329 | local v = 8 * (1.1 - mass / Player.MAX_PICKABLE_OBJECT_MASS) -- speed between 0.8 and 8.8 based on mass of current object |
2330 | local halfSqrt = 0.707106781 |
2331 | -- Add the impulse in 45deg towards the y axis of the camera |
2332 | local vx,vy,vz = localDirectionToWorld(self.cameraNode, 0.0, halfSqrt * v, -halfSqrt * v) |
2333 | setLinearVelocity(self.lastFoundObject, vx, vy, vz) |
2334 | end |
2335 | end |
2336 | end |
touchEventLookLeftRight
DescriptionDefinitiontouchEventLookLeftRight()Code
2945 | function Player:touchEventLookLeftRight(value) |
2946 | if self:getIsInputAllowed() then |
2947 | local factor = (g_screenWidth / g_screenHeight) * 100 |
2948 | Player.onInputLookLeftRight(self, nil, value * factor, nil, nil, false) |
2949 | end |
2950 | end |
touchEventLookUpDown
DescriptionDefinitiontouchEventLookUpDown()Code
2970 | function Player:touchEventLookUpDown(value) |
2971 | if self:getIsInputAllowed() then |
2972 | local factor = (g_screenHeight / g_screenWidth) * -100 |
2973 | Player.onInputLookUpDown(self, nil, value * factor, nil, nil, false) |
2974 | end |
2975 | end |
unequipHandtool
DescriptionDefinitionunequipHandtool()Code
2042 | function Player:unequipHandtool() |
2043 | self:equipHandtool("", true) |
2044 | end |
update
DescriptionMain update function for the player. Taking care of: fx, water parms, sound, player states, motion, debug, action events, hand tools, animation, object picking, IKDefinition
update(float dt)Arguments
float | dt | delta time in ms |
823 | function Player:update(dt) |
824 | self.time = self.time + dt |
825 | |
826 | -- print(string.format("-- [Player:update][%s] isEntered(%s) isServer(%s) isClient(%s) isControlled(%s)", tostring(self), tostring(self.isEntered), tostring(self.isServer), tostring(self.isClient), tostring(self.isControlled))) |
827 | if not self.isEntered and self.isClient and self.isControlled then |
828 | self:updateFX() |
829 | end |
830 | |
831 | -- check if the player is on ground |
832 | if self.isServer or self.isEntered then |
833 | local _, _, isOnGround = getCCTCollisionFlags(self.controllerIndex) |
834 | self.baseInformation.isOnGroundPhysics = isOnGround |
835 | end |
836 | |
837 | if self.isClient and self.isControlled then |
838 | self:updateWaterParams() |
839 | if Platform.hasPlayer then |
840 | self:updateSound() |
841 | end |
842 | end |
843 | |
844 | if self.isEntered and self.isClient and not g_gui:getIsGuiVisible() then |
845 | if not g_currentMission.isPlayerFrozen then |
846 | self:updatePlayerStates() |
847 | self.playerStateMachine:update(dt) |
848 | self:recordPositionInformation() |
849 | |
850 | local bobDelta = 0 |
851 | if self.cameraBobbingEnabled and not self.thirdPersonViewActive then |
852 | bobDelta = self:cameraBob(dt) |
853 | end |
854 | self:updateCameraTranslation(bobDelta) |
855 | |
856 | self:debugDraw() |
857 | self.playerStateMachine:debugDraw(dt) |
858 | |
859 | if not self.walkingIsLocked then |
860 | self.rotX = self.rotX - self.inputInformation.pitchCamera * g_gameSettings:getValue(GameSettings.SETTING.CAMERA_SENSITIVITY) |
861 | self.rotY = self.rotY - self.inputInformation.yawCamera * g_gameSettings:getValue(GameSettings.SETTING.CAMERA_SENSITIVITY) |
862 | |
863 | if self.thirdPersonViewActive then |
864 | self.rotX = math.min(0, math.max(-1, self.rotX)) |
865 | |
866 | -- Rotate camera target around player |
867 | setRotation(self.thirdPersonLookatNode, -self.rotX, self.rotY, 0) |
868 | |
869 | -- DebugUtil.drawDebugNode(self.thirdPersonLookatNode, "thirdPersonLookatNode", false) |
870 | -- DebugUtil.drawDebugNode(self.thirdPersonLookfromNode, "thirdPersonLookfromNode", false) |
871 | else |
872 | self.rotX = math.min(1.2, math.max(-1.5, self.rotX)) |
873 | setRotation(self.cameraNode, self.rotX, self.rotY, 0) |
874 | setRotation(self.foliageBendingNode, 0, self.rotY, 0) |
875 | end |
876 | end |
877 | self:updateActionEvents() |
878 | |
879 | local x, y, z = getWorldTranslation(self.cameraNode) |
880 | g_currentMission.activatableObjectsSystem:setPosition(x, y, z) |
881 | end |
882 | end |
883 | |
884 | if self:hasHandtoolEquipped() then |
885 | self.baseInformation.currentHandtool:update(dt, self:getIsInputAllowed()) |
886 | |
887 | if self.playerStateMachine:isActive("swim") then |
888 | self:unequipHandtool() |
889 | end |
890 | end |
891 | |
892 | self:updateInterpolation() |
893 | |
894 | local isModelVisible = (self.isClient and self.isControlled) or self.thirdPersonViewActive |
895 | |
896 | if isModelVisible then |
897 | self:updateRotation(dt) |
898 | end |
899 | |
900 | -- animation |
901 | if self.isClient and self.isControlled and (not self.isEntered or isModelVisible) then |
902 | self:updateAnimationParameters(dt) |
903 | self.model:updateAnimations(dt) |
904 | |
905 | -- Animation Debug |
906 | --local a,b,c = getWorldTranslation(self.rootNode) |
907 | --b = b + 1.0 |
908 | --conditionalAnimationDebugDraw(self.model.animationInformation.player, a,b,c) |
909 | end |
910 | |
911 | -- objects in front of player: server needs to update controlled clients, clients only themselves |
912 | if self.allowPlayerPickUp and self.isControlled and (self.isServer or self.isEntered) then |
913 | self:checkObjectInRange() |
914 | end |
915 | |
916 | -- if self.isEntered or (self.isControlled and self.networkInformation.interpolationTime.isDirty) then |
917 | if self.isEntered or self.networkInformation.interpolationTime.isDirty then |
918 | self:raiseActive() |
919 | end |
920 | |
921 | if self.isClient and self.isControlled and not self.isEntered and self.networkInformation.rotateObject then |
922 | self:rotateObject(self.networkInformation.rotateObjectInputV, 1.0, 0.0, 0.0) |
923 | self:rotateObject(self.networkInformation.rotateObjectInputH, 0.0, 1.0, 0.0) |
924 | end |
925 | self:resetCameraInputsInformation() |
926 | |
927 | if self.isEntered then |
928 | self.hudUpdater:update(dt, self:getPositionData()) |
929 | end |
930 | end |
updateActionEvents
DescriptionUpdate action event states and input hint display.Definition
updateActionEvents()Code
1011 | function Player:updateActionEvents() |
1012 | -- light |
1013 | local isDark = not g_currentMission.environment.isSunOn |
1014 | local eventIdToggleLight = self.inputInformation.registrationList[InputAction.TOGGLE_LIGHTS_FPS].eventId |
1015 | if self.playerStateMachine:isAvailable("useLight") and isDark then |
1016 | g_inputBinding:setActionEventTextVisibility(eventIdToggleLight, isDark and self.model:getHasTorch()) |
1017 | end |
1018 | |
1019 | local stateSwitchHandTool = false |
1020 | local stateActivateHandTool = false |
1021 | local stateInteract = false |
1022 | local stateAnimalPet = false |
1023 | local stateEnter = false |
1024 | local stateThrowObject = false |
1025 | local stateObjectLeftRight = false |
1026 | local stateObjectUpDown = false |
1027 | |
1028 | -- tools |
1029 | if self.playerStateMachine:isAvailable("cycleHandtool") then |
1030 | stateSwitchHandTool = true |
1031 | end |
1032 | |
1033 | if self:hasHandtoolEquipped() then |
1034 | stateActivateHandTool = true |
1035 | self.playerStateMachine:isAvailable("activateObject") |
1036 | else |
1037 | if self.playerStateMachine:isAvailable("throw") then |
1038 | stateThrowObject = true |
1039 | end |
1040 | |
1041 | if self.isCarryingObject then |
1042 | stateObjectLeftRight = true |
1043 | stateObjectUpDown = true |
1044 | end |
1045 | |
1046 | if self.playerStateMachine:isAvailable("animalPet") then |
1047 | local eventIdActivateObject = self.inputInformation.registrationList[InputAction.ANIMAL_PET].eventId |
1048 | stateAnimalPet = true |
1049 | g_inputBinding:setActionEventText(eventIdActivateObject, g_i18n:getText("action_petAnimal")) |
1050 | end |
1051 | |
1052 | local eventIdInteract = self.inputInformation.registrationList[InputAction.INTERACT].eventId |
1053 | if self.playerStateMachine:isAvailable("drop") then |
1054 | g_inputBinding:setActionEventText(eventIdInteract, g_i18n:getText("action_dropObject")) |
1055 | stateInteract = true |
1056 | elseif self.playerStateMachine:isAvailable("pickup") then |
1057 | g_inputBinding:setActionEventText(eventIdInteract, g_i18n:getText("action_pickUpObject")) |
1058 | stateInteract = true |
1059 | elseif self.playerStateMachine:isAvailable("animalInteract") or self.playerStateMachine:isActive("animalInteract") then |
1060 | local animalInteractState = self.playerStateMachine:getState("animalInteract") |
1061 | local animalInteractText = string.format(g_i18n:getText("action_interactAnimal"), animalInteractState.interactText) |
1062 | g_inputBinding:setActionEventText(eventIdInteract, animalInteractText) |
1063 | stateInteract = true |
1064 | end |
1065 | end |
1066 | |
1067 | -- enter vehicle or ride animal |
1068 | self.canRideAnimal = self.playerStateMachine:isAvailable("animalRide") |
1069 | self.canEnterVehicle = g_currentMission.interactiveVehicleInRange and g_currentMission.interactiveVehicleInRange:getIsEnterable() |
1070 | local vehicleIsRideable = self.canEnterVehicle and SpecializationUtil.hasSpecialization(Rideable, g_currentMission.interactiveVehicleInRange.specializations) |
1071 | local eventIdEnter = self.inputInformation.registrationList[InputAction.ENTER].eventId |
1072 | if self.canEnterVehicle and not vehicleIsRideable then |
1073 | g_inputBinding:setActionEventText(eventIdEnter, g_i18n:getText("button_enterVehicle")) |
1074 | stateEnter = true |
1075 | elseif self.canRideAnimal or vehicleIsRideable then |
1076 | local rideableName = "" |
1077 | if self.canRideAnimal then |
1078 | local rideState = self.playerStateMachine:getState("animalRide") |
1079 | rideableName = rideState:getRideableName() |
1080 | elseif vehicleIsRideable then |
1081 | rideableName = g_currentMission.interactiveVehicleInRange:getFullName() |
1082 | end |
1083 | g_inputBinding:setActionEventText(eventIdEnter, string.format(g_i18n:getText("action_rideAnimal"), rideableName)) |
1084 | stateEnter = true |
1085 | end |
1086 | |
1087 | -- first disable all inactive inputs to avoid conflicts if not active in this frame |
1088 | self:disableInput(InputAction.SWITCH_HANDTOOL, stateSwitchHandTool) |
1089 | self:disableInput(InputAction.ACTIVATE_HANDTOOL, stateActivateHandTool) |
1090 | self:disableInput(InputAction.INTERACT, stateInteract) |
1091 | self:disableInput(InputAction.ANIMAL_PET, stateAnimalPet) |
1092 | self:disableInput(InputAction.ENTER, stateEnter) |
1093 | self:disableInput(InputAction.THROW_OBJECT, stateThrowObject) |
1094 | self:disableInput(InputAction.ROTATE_OBJECT_LEFT_RIGHT, stateObjectLeftRight) |
1095 | self:disableInput(InputAction.ROTATE_OBJECT_UP_DOWN, stateObjectUpDown) |
1096 | |
1097 | self:setInputState(InputAction.SWITCH_HANDTOOL, stateSwitchHandTool) |
1098 | self:setInputState(InputAction.ACTIVATE_HANDTOOL, stateActivateHandTool) |
1099 | self:setInputState(InputAction.INTERACT, stateInteract) |
1100 | self:setInputState(InputAction.ANIMAL_PET, stateAnimalPet) |
1101 | self:setInputState(InputAction.ENTER, stateEnter) |
1102 | self:setInputState(InputAction.THROW_OBJECT, stateThrowObject) |
1103 | self:setInputState(InputAction.ROTATE_OBJECT_LEFT_RIGHT, stateObjectLeftRight) |
1104 | self:setInputState(InputAction.ROTATE_OBJECT_UP_DOWN, stateObjectUpDown) |
1105 | |
1106 | |
1107 | -- debug movements |
1108 | local eventIdDebugFlyToggle = self.inputInformation.registrationList[InputAction.DEBUG_PLAYER_ENABLE].eventId |
1109 | g_inputBinding:setActionEventActive(eventIdDebugFlyToggle, g_flightModeEnabled) |
1110 | local eventIdDebugFlyUpDown = self.inputInformation.registrationList[InputAction.DEBUG_PLAYER_UP_DOWN].eventId |
1111 | g_inputBinding:setActionEventActive(eventIdDebugFlyUpDown, g_flightModeEnabled) |
1112 | end |
updateAnimationParameters
DescriptionUpdates the parameters that will drive the animationDefinition
updateAnimationParameters(float dt)Arguments
float | dt | delta time in ms |
759 | function Player:updateAnimationParameters(dt) |
760 | local ni = self.networkInformation |
761 | --local dx = (ni.interpolatorPosition.targetPositionX - ni.interpolatorPosition.lastPositionX) |
762 | local dy = (ni.interpolatorPosition.targetPositionY - ni.interpolatorPosition.lastPositionY) |
763 | --local dz = (ni.interpolatorPosition.targetPositionZ - ni.interpolatorPosition.lastPositionZ) |
764 | --local vx = dx / (ni.interpolationTime.interpolationDuration * 0.001) |
765 | local vy = dy / (ni.interpolationTime.interpolationDuration * 0.001) |
766 | --local vz = dz / (ni.interpolationTime.interpolationDuration * 0.001) |
767 | --local dirX, dirZ = math.sin(self.graphicsRotY), math.cos(self.graphicsRotY) |
768 | --local estimatedForwardVelocity = vx * dirX + vz * dirZ |
769 | -- @see using calculation in Player:updateRotation() for a less unstable speed |
770 | -- self.lastEstimatedForwardVelocity = self.lastEstimatedForwardVelocity * 0.5 + estimatedForwardVelocity * 0.5 |
771 | |
772 | if not self.isEntered and self.baseInformation.animDt ~= nil and self.baseInformation.animDt ~= 0 then |
773 | self.oldYaw = self.newYaw |
774 | self.newYaw = self.cameraRotY |
775 | self.estimatedYawVelocity = MathUtil.getAngleDifference(self.newYaw, self.oldYaw) / (self.baseInformation.animDt * 0.001) |
776 | self.baseInformation.animDt = 0 |
777 | end |
778 | |
779 | local bi = self.baseInformation |
780 | self.model:setAnimationParameters(bi.isOnGround, bi.isInWater, bi.isCrouched, bi.isCloseToGround, self.lastEstimatedForwardVelocity, vy, self.estimatedYawVelocity) |
781 | end |
updateFX
DescriptionUpdate particle FX.Definition
updateFX()Code
2400 | function Player:updateFX() |
2401 | local x, y, z = getWorldTranslation(self.rootNode) |
2402 | |
2403 | self.model:updateFX(x, y, z, self.baseInformation.isInWater, self.baseInformation.plungedInWater, self.waterY) |
2404 | end |
updateInterpolation
DescriptionUpdates interpolations for physics, camera and positionDefinition
updateInterpolation()Code
1157 | function Player:updateInterpolation() |
1158 | if self.isControlled then |
1159 | local needsCameraInterp = self.isServer and not self.isEntered |
1160 | local needsPositionInterp = self.isClient |
1161 | |
1162 | if needsCameraInterp or needsPositionInterp then |
1163 | if self.networkInformation.interpolationTime.isDirty then |
1164 | self.networkInformation.interpolationTime:update(g_physicsDtUnclamped) |
1165 | if needsCameraInterp then |
1166 | local qx, qy, qz, qw = self.networkInformation.interpolatorQuaternion:getInterpolatedValues(self.networkInformation.interpolationTime.interpolationAlpha) |
1167 | |
1168 | setQuaternion(self.cameraNode, qx, qy, qz, qw) |
1169 | end |
1170 | if needsPositionInterp then |
1171 | local x, y, z = self.networkInformation.interpolatorPosition:getInterpolatedValues(self.networkInformation.interpolationTime.interpolationAlpha) |
1172 | |
1173 | -- xyz is center of the CCT capsule. We subtract a radius and half the height to get to ground level |
1174 | local radius, height = self.model:getCapsuleSize() |
1175 | setTranslation(self.graphicsRootNode, x, y - radius - height / 2, z) |
1176 | |
1177 | local isOnGroundFloat = self.networkInformation.interpolatorOnGround:getInterpolatedValue(self.networkInformation.interpolationTime.interpolationAlpha) |
1178 | self.baseInformation.isOnGround = isOnGroundFloat > 0.99 |
1179 | self.baseInformation.isCloseToGround = isOnGroundFloat > 0.01 |
1180 | end |
1181 | end |
1182 | end |
1183 | end |
1184 | end |
updateInterpolationTick
DescriptionUpdates interpolations for physics, camera and positionDefinition
updateInterpolationTick()Code
1116 | function Player:updateInterpolationTick() |
1117 | if self.isEntered then |
1118 | local xt, yt, zt = getTranslation(self.rootNode) |
1119 | |
1120 | -- Reuse the existing target position if the change is very small to avoid jitter |
1121 | local interpPos = self.networkInformation.interpolatorPosition |
1122 | if math.abs(xt-interpPos.targetPositionX) < 0.001 and math.abs(yt-interpPos.targetPositionY) < 0.001 and math.abs(zt-interpPos.targetPositionZ) < 0.001 then |
1123 | xt, yt, zt = interpPos.targetPositionX, interpPos.targetPositionY, interpPos.targetPositionZ |
1124 | end |
1125 | self.networkInformation.interpolatorPosition:setTargetPosition(xt, yt, zt) |
1126 | |
1127 | if self.baseInformation.isOnGroundPhysics then |
1128 | self.networkInformation.interpolatorOnGround:setTargetValue(1.0) |
1129 | else |
1130 | self.networkInformation.interpolatorOnGround:setTargetValue(0.0) |
1131 | end |
1132 | self.networkInformation.interpolationTime:startNewPhase(75) |
1133 | elseif self.networkInformation.updateTargetTranslationPhysicsIndex >= 0 then |
1134 | local xt, yt, zt = getTranslation(self.rootNode) |
1135 | if getIsPhysicsUpdateIndexSimulated(self.networkInformation.updateTargetTranslationPhysicsIndex) then |
1136 | self.networkInformation.updateTargetTranslationPhysicsIndex = -1 |
1137 | else |
1138 | -- Reuse the existing target position if the change is very small to avoid jitter |
1139 | local interpPos = self.networkInformation.interpolatorPosition |
1140 | if math.abs(xt-interpPos.targetPositionX) < 0.001 and math.abs(yt-interpPos.targetPositionY) < 0.001 and math.abs(zt-interpPos.targetPositionZ) < 0.001 then |
1141 | xt, yt, zt = interpPos.targetPositionX, interpPos.targetPositionY, interpPos.targetPositionZ |
1142 | end |
1143 | end |
1144 | self.networkInformation.interpolatorPosition:setTargetPosition(xt, yt, zt) |
1145 | if self.baseInformation.isOnGroundPhysics then |
1146 | self.networkInformation.interpolatorOnGround:setTargetValue(1.0) |
1147 | else |
1148 | self.networkInformation.interpolatorOnGround:setTargetValue(0.0) |
1149 | end |
1150 | self.networkInformation.interpolatorQuaternion:setTargetQuaternion(self.networkInformation.interpolatorQuaternion.targetQuaternionX, self.networkInformation.interpolatorQuaternion.targetQuaternionY, self.networkInformation.interpolatorQuaternion.targetQuaternionZ, self.networkInformation.interpolatorQuaternion.targetQuaternionW) |
1151 | self.networkInformation.interpolationTime:startNewPhase(75) |
1152 | end |
1153 | end |
updateKinematic
DescriptionUpdates player movement depending on inputs (run, crouch, swim) and apply gravityDefinition
updateKinematic()Code
2636 | function Player:updateKinematic(dt) |
2637 | local dtInSec = dt * 0.001 |
2638 | local inputX = self.inputInformation.moveRight |
2639 | local inputZ = self.inputInformation.moveForward |
2640 | if inputX ~= 0.0 or inputZ ~= 0.0 then |
2641 | local normInputX, normInputZ = MathUtil.vector2Normalize(inputX, inputZ) |
2642 | local _ |
2643 | self.motionInformation.currentWorldDirX, _, self.motionInformation.currentWorldDirZ = localDirectionToWorld(self.cameraNode, normInputX, 0.0, normInputZ) |
2644 | self.motionInformation.currentWorldDirX, self.motionInformation.currentWorldDirZ = MathUtil.vector2Normalize(self.motionInformation.currentWorldDirX, self.motionInformation.currentWorldDirZ) |
2645 | end |
2646 | local desiredSpeed = self:getDesiredSpeed() |
2647 | local desiredSpeedX = self.motionInformation.currentWorldDirX * desiredSpeed |
2648 | local desiredSpeedZ = self.motionInformation.currentWorldDirZ * desiredSpeed |
2649 | |
2650 | local speedChangeX = (desiredSpeedX - self.motionInformation.currentSpeedX) |
2651 | local speedChangeZ = (desiredSpeedZ - self.motionInformation.currentSpeedZ) |
2652 | |
2653 | if not self.baseInformation.isOnGround then |
2654 | -- reduce acceleration when in the air |
2655 | speedChangeX = speedChangeX * 0.2 |
2656 | speedChangeZ = speedChangeZ * 0.2 |
2657 | end |
2658 | |
2659 | self.motionInformation.currentSpeedX = self.motionInformation.currentSpeedX + speedChangeX |
2660 | self.motionInformation.currentSpeedZ = self.motionInformation.currentSpeedZ + speedChangeZ |
2661 | self.motionInformation.currentSpeed = math.sqrt(self.motionInformation.currentSpeedX * self.motionInformation.currentSpeedX + self.motionInformation.currentSpeedZ * self.motionInformation.currentSpeedZ) |
2662 | |
2663 | local movementX = self.motionInformation.currentSpeedX * dtInSec |
2664 | local movementY = 0.0 |
2665 | local movementZ = self.motionInformation.currentSpeedZ * dtInSec |
2666 | |
2667 | -- Swim adjustment |
2668 | local _, y, _ = getWorldTranslation(self.rootNode) |
2669 | local deltaWater = y - self.waterY - self.model.capsuleTotalHeight * 0.5 |
2670 | local waterLevel = self.baseInformation.waterLevel |
2671 | |
2672 | local distToWaterLevel = deltaWater - waterLevel |
2673 | |
2674 | if distToWaterLevel > 0.001 then |
2675 | -- Update gravity / vertical movement |
2676 | local gravityFactor = 3.0 -- for falling faster |
2677 | local gravitySpeedChange = gravityFactor * self.motionInformation.gravity * dtInSec |
2678 | self.motionInformation.currentSpeedY = math.max(self.motionInformation.currentSpeedY + gravitySpeedChange, self.motionInformation.gravity * 7.0) -- clamp after 7s of falling |
2679 | if distToWaterLevel < self.model.capsuleTotalHeight * 0.5 then |
2680 | -- hack to reduce unsteability in low framerate |
2681 | movementY = math.max(self.motionInformation.currentSpeedY * dtInSec, -distToWaterLevel * 0.5) |
2682 | else |
2683 | movementY = math.max(self.motionInformation.currentSpeedY * dtInSec, -distToWaterLevel) |
2684 | end |
2685 | self.motionInformation.currentSpeedY = movementY / math.max(dtInSec, 0.000001) -- calc actual speed with clamped movement |
2686 | elseif distToWaterLevel < -0.01 then |
2687 | local buoyancySpeed = -self.motionInformation.gravity |
2688 | movementY = math.min(buoyancySpeed * dtInSec, -distToWaterLevel) |
2689 | self.motionInformation.currentSpeedY = movementY / math.max(dtInSec, 0.000001) -- calc actual speed with clamped movement |
2690 | else |
2691 | self.motionInformation.currentSpeedY = 0.0 |
2692 | end |
2693 | |
2694 | self:movePlayer(dt, movementX, movementY, movementZ) |
2695 | end |
updateNetworkMovementHistory
DescriptionDefinitionupdateNetworkMovementHistory()Code
1188 | function Player:updateNetworkMovementHistory() |
1189 | if self.isEntered and self.isClient then |
1190 | self:raiseDirtyFlags(self.networkInformation.dirtyFlag) |
1191 | elseif self.isServer and not self.isEntered and self.isControlled then |
1192 | -- find the latest index, which is already simulated now |
1193 | local latestSimulatedIndex = -1 |
1194 | while self.networkInformation.history[1] ~= nil and getIsPhysicsUpdateIndexSimulated(self.networkInformation.history[1].physicsIndex) do |
1195 | latestSimulatedIndex = self.networkInformation.history[1].index |
1196 | table.remove(self.networkInformation.history, 1) |
1197 | end |
1198 | if latestSimulatedIndex >= 0 then |
1199 | self.networkInformation.sendIndex = latestSimulatedIndex |
1200 | self:raiseDirtyFlags(self.networkInformation.dirtyFlag) |
1201 | end |
1202 | end |
1203 | end |
updatePlayerStates
DescriptionUpdates player state machineDefinition
updatePlayerStates()Code
2699 | function Player:updatePlayerStates() |
2700 | if self.playerStateMachine:isAvailable("fall") then |
2701 | self.playerStateMachine:activateState("fall") |
2702 | end |
2703 | |
2704 | if self.baseInformation.waterDepth > 0.4 then |
2705 | self.playerStateMachine:deactivateState("crouch") |
2706 | end |
2707 | |
2708 | if self.baseInformation.isInWater and self.playerStateMachine:isAvailable("swim") then |
2709 | self.playerStateMachine:activateState("swim") |
2710 | end |
2711 | |
2712 | if (self.inputInformation.moveForward ~= 0) or (self.inputInformation.moveRight ~= 0) then |
2713 | if (self.inputInformation.runAxis > 0.0) and self.playerStateMachine:isAvailable("run") then |
2714 | self.playerStateMachine:activateState("run") |
2715 | elseif self.playerStateMachine:isAvailable("walk") then |
2716 | self.playerStateMachine:activateState("walk") |
2717 | end |
2718 | else |
2719 | self.playerStateMachine:activateState("idle") |
2720 | end |
2721 | end |
updateRotation
DescriptionUpdates rotation of player avatar over the networkDefinition
updateRotation(float dt)Arguments
float | dt | delta time in ms |
1208 | function Player:updateRotation(dt) |
1209 | if not self.isEntered then |
1210 | local animDt = 60 |
1211 | self.animUpdateTime = self.animUpdateTime + dt |
1212 | if self.animUpdateTime > animDt then |
1213 | if self.isServer then |
1214 | local x, _, z = localDirectionToLocal(self.cameraNode, getParent(self.cameraNode), 0, 0, 1) |
1215 | local alpha = math.atan2(x, z) |
1216 | self.cameraRotY = alpha |
1217 | end |
1218 | |
1219 | local x, y, z = getTranslation(self.graphicsRootNode) |
1220 | local dx, _, dz = x - self.lastAnimPosX, y - self.lastAnimPosY, z - self.lastAnimPosZ |
1221 | local dirX, dirZ = -math.sin(self.cameraRotY), -math.cos(self.cameraRotY) |
1222 | local movementDist = dx * dirX + dz * dirZ -- Note: |dir| = 1 |
1223 | |
1224 | if (dx * dx + dz * dz) < 0.001 then |
1225 | self.targetGraphicsRotY = self.cameraRotY + math.rad(180.0) |
1226 | else |
1227 | if movementDist > -0.001 then |
1228 | self.targetGraphicsRotY = math.atan2(dx, dz) |
1229 | else |
1230 | self.targetGraphicsRotY = math.atan2(-dx, -dz) |
1231 | end |
1232 | end |
1233 | |
1234 | dirX, dirZ = -math.sin(self.targetGraphicsRotY), -math.cos(self.targetGraphicsRotY) |
1235 | movementDist = dx * dirX + dz * dirZ -- Note: |dir| = 1 |
1236 | movementDist = self.walkDistance * 0.2 + movementDist * 0.8 |
1237 | self.walkDistance = movementDist |
1238 | self.lastEstimatedForwardVelocity = -movementDist / (self.animUpdateTime * 0.001) |
1239 | |
1240 | self.lastAnimPosX = x |
1241 | self.lastAnimPosY = y |
1242 | self.lastAnimPosZ = z |
1243 | |
1244 | self.baseInformation.animDt = self.animUpdateTime |
1245 | self.animUpdateTime = 0 |
1246 | end |
1247 | |
1248 | self.targetGraphicsRotY = MathUtil.normalizeRotationForShortestPath(self.targetGraphicsRotY, self.graphicsRotY) |
1249 | local maxDeltaRotY = math.rad(0.5) * dt |
1250 | self.graphicsRotY = math.min(math.max(self.targetGraphicsRotY, self.graphicsRotY - maxDeltaRotY), self.graphicsRotY + maxDeltaRotY) |
1251 | |
1252 | self.model:setSkeletonRotation(self.graphicsRotY) |
1253 | elseif self.thirdPersonViewActive then |
1254 | local x, y, z = getTranslation(self.graphicsRootNode) |
1255 | local dx, _, dz = x - self.lastAnimPosX, y - self.lastAnimPosY, z - self.lastAnimPosZ |
1256 | |
1257 | local horizontalSpeed = math.sqrt(dx * dx + dz * dz) |
1258 | self.horizontalSpeed = horizontalSpeed |
1259 | self.lastEstimatedForwardVelocity = horizontalSpeed / (dt * 0.001) |
1260 | |
1261 | -- At speed 0, dirY is also 0 so it always resets to a base rotation. |
1262 | if horizontalSpeed > 0.0001 then |
1263 | local dirY = MathUtil.getYRotationFromDirection(dx, dz) |
1264 | local newY = self.graphicsRotY |
1265 | |
1266 | local diff = (dirY - newY) / (dt * 0.05) |
1267 | diff = MathUtil.clamp(diff, -0.1, 0.1) |
1268 | |
1269 | newY = newY + diff |
1270 | |
1271 | self.graphicsRotY = newY |
1272 | self.model:setSkeletonRotation(newY) |
1273 | self.cameraRotY = newY |
1274 | end |
1275 | |
1276 | self.oldYaw = self.newYaw |
1277 | self.newYaw = self.cameraRotY |
1278 | |
1279 | -- Used for player rotation in animation |
1280 | self.estimatedYawVelocity = MathUtil.getAngleDifference(self.newYaw, self.oldYaw) / dt * math.min(self.horizontalSpeed * 50, 10) |
1281 | |
1282 | self.lastAnimPosX = x |
1283 | self.lastAnimPosY = y |
1284 | self.lastAnimPosZ = z |
1285 | |
1286 | self.baseInformation.animDt = dt |
1287 | end |
1288 | end |
updateSound
DescriptionUpdate sound for the player: steps (when crouch, walk, run), swim, plungeDefinition
updateSound()Code
2356 | function Player:updateSound() |
2357 | local isCrouching, isWalking, isRunning, isSwimming |
2358 | local forwardVel |
2359 | |
2360 | isCrouching = self.playerStateMachine:isActive("crouch") |
2361 | isSwimming = self.playerStateMachine:isActive("swim") |
2362 | |
2363 | if not self.isEntered then |
2364 | forwardVel = self.model:getLastForwardVelocity() |
2365 | |
2366 | if isCrouching then |
2367 | elseif math.abs(forwardVel) <= self.motionInformation.maxWalkingSpeed then |
2368 | isWalking = true |
2369 | elseif math.abs(forwardVel) > self.motionInformation.maxWalkingSpeed then |
2370 | isRunning = true |
2371 | end |
2372 | else |
2373 | forwardVel = math.abs(self.motionInformation.currentSpeed) |
2374 | isWalking = self.playerStateMachine:isActive("walk") |
2375 | isRunning = self.playerStateMachine:isActive("run") |
2376 | end |
2377 | |
2378 | -- Detect when we start jumping or when we dropped to the ground for one-shot sound effects |
2379 | local didJump = false |
2380 | local isJumping = self.playerStateMachine:isActive("jump") |
2381 | if self.wasJumping ~= isJumping then |
2382 | self.wasJumping = isJumping |
2383 | |
2384 | didJump = isJumping |
2385 | end |
2386 | |
2387 | local isDropping = self.playerStateMachine:isActive("fall") |
2388 | local didTouchGround = false |
2389 | if self.wasDropping ~= isDropping then |
2390 | self.wasDropping = isDropping |
2391 | |
2392 | didTouchGround = not isDropping |
2393 | end |
2394 | |
2395 | self.model:setSoundParameters(forwardVel, isCrouching, isWalking, isRunning, isSwimming, self.baseInformation.plungedInWater, self.baseInformation.isInWater, self.motionInformation.coveredGroundDistance, self.motionInformation.maxSwimmingSpeed, self.baseInformation.waterLevel, didJump, didTouchGround, self.waterY) |
2396 | end |
updateTick
DescriptionUpdate function called when network ticks. Takes care of movements/position, player state machine, interpolation phase, physics, handtools. Inputs are reset here.Definition
updateTick(float dt)Arguments
float | dt | delta time in ms |
935 | function Player:updateTick(dt) |
936 | if self.isEntered and not g_gui:getIsGuiVisible() and not g_currentMission.isPlayerFrozen then |
937 | self:updateKinematic(dt) |
938 | end |
939 | |
940 | self.playerStateMachine:updateTick(dt) |
941 | |
942 | if self:hasHandtoolEquipped() then |
943 | self.baseInformation.currentHandtool:updateTick(dt, self:getIsInputAllowed()) |
944 | end |
945 | self:updateNetworkMovementHistory() |
946 | self:updateInterpolationTick() |
947 | |
948 | self:resetInputsInformation() |
949 | |
950 | |
951 | -- ------------------------- |
952 | -- @todo: check and add again |
953 | -- ------------------------- |
954 | -- local xt, yt, zt = getTranslation(self.rootNode) |
955 | -- --[[ |
956 | -- if GS_PLATFORM_PLAYSTATION or GS_PLATFORM_XBOX then |
957 | -- xt = xt + self.movementX |
958 | -- zt = zt + self.movementZ |
959 | -- yt = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, xt, 300, zt) + self.height |
960 | -- setTranslation(self.rootNode, xt, yt, zt) |
961 | -- end |
962 | -- --]] |
963 | -- ------------------------- |
964 | if self.isServer and self.isControlled then |
965 | if not GS_PLATFORM_PC then |
966 | local x, y, z = getTranslation(self.rootNode) |
967 | local paramsXZ = g_currentMission.vehicleXZPosCompressionParams |
968 | if not NetworkUtil.getIsWorldPositionInCompressionRange(x, paramsXZ) or |
969 | not NetworkUtil.getIsWorldPositionInCompressionRange(z, paramsXZ) or |
970 | getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, y, z) > y + 20 |
971 | then |
972 | self:moveTo(g_currentMission.playerStartX, g_currentMission.playerStartY, g_currentMission.playerStartZ, g_currentMission.playerStartIsAbsolute, false) |
973 | return |
974 | end |
975 | end |
976 | end |
977 | -- ------------------------- |
978 | |
979 | -- Prevent player from getting stuck in a high level of snow |
980 | if self.isControlled and not self.noClipEnabled then -- disable if noClip mode is enabled to allow moving below the terrain |
981 | local px, py, pz = getTranslation(self.rootNode) |
982 | local dy = DensityMapHeightUtil.getCollisionHeightAtWorldPos(px, py, pz) |
983 | |
984 | local heightOffset = 0.5 * self.model.capsuleHeight -- for root node origin to terrain |
985 | if py < dy + heightOffset - 0.1 then |
986 | py = dy + heightOffset + 0.05 -- 5cm above so no clipping occurs. Gravity will fix it. |
987 | setTranslation(self.rootNode, px, py, pz) |
988 | end |
989 | end |
990 | end |
updateWaterParams
DescriptionUpdates information related to the player and the water level. It is used for particle effects when plunging and checking if the player is in water.Definition
updateWaterParams()Code
785 | function Player:updateWaterParams() |
786 | local x, y, z = getWorldTranslation(self.rootNode) |
787 | local yw = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, y, z) |
788 | |
789 | g_currentMission.environmentAreaSystem:getWaterYAtWorldPositionAsync(x, y, z, function(_, waterY) |
790 | self.waterY = waterY or -2000 |
791 | end, nil, nil) |
792 | |
793 | local playerY = y - self.model.capsuleTotalHeight * 0.5 |
794 | local deltaWater = playerY - self.waterY |
795 | |
796 | local waterLevel = self.baseInformation.waterLevel |
797 | local velocityY |
798 | |
799 | if deltaWater < -50 then |
800 | return |
801 | end |
802 | |
803 | if not self.isEntered then |
804 | velocityY = self.model.animationInformation.parameters.verticalVelocity.value |
805 | else |
806 | velocityY = self.motionInformation.currentSpeedY |
807 | end |
808 | |
809 | self.baseInformation.wasInWater = self.baseInformation.isInWater |
810 | self.baseInformation.isInWater = deltaWater <= waterLevel |
811 | self.baseInformation.waterDepth = math.max(0, self.waterY - playerY) |
812 | |
813 | if not self.baseInformation.wasInWater and self.baseInformation.isInWater and velocityY < self.baseInformation.plungedYVelocityThreshold then |
814 | self.baseInformation.plungedInWater = true |
815 | else |
816 | self.baseInformation.plungedInWater = false |
817 | end |
818 | end |
writeStream
DescriptionWrites in network streamDefinition
writeStream(integer streamId, table connection)Arguments
integer | streamId | id of the stream to read |
table | connection | connection information |
500 | function Player:writeStream(streamId, connection) |
501 | Player:superClass().writeStream(self, streamId, connection) |
502 | streamWriteBool(streamId, connection == self.networkInformation.creatorConnection) |
503 | |
504 | local x, y, z = getTranslation(self.rootNode) |
505 | streamWriteFloat32(streamId, x) |
506 | streamWriteFloat32(streamId, y) |
507 | streamWriteFloat32(streamId, z) |
508 | |
509 | streamWriteBool(streamId, self.isControlled) |
510 | |
511 | streamWriteUIntN(streamId, self.farmId, FarmManager.FARM_ID_SEND_NUM_BITS) |
512 | NetworkUtil.writeNodeObjectId(streamId, self.userId) |
513 | |
514 | streamWriteBool(streamId, self.isTorchActive) |
515 | |
516 | local hasHandtool = self:hasHandtoolEquipped() |
517 | streamWriteBool(streamId, hasHandtool) |
518 | if hasHandtool then |
519 | streamWriteString(streamId, NetworkUtil.convertToNetworkFilename(self.baseInformation.currentHandtool.configFileName)) |
520 | end |
521 | end |
writeUpdateStream
DescriptionWrites to network stream via updateDefinition
writeUpdateStream(integer streamId, integer timestamp, table connection)Arguments
integer | streamId | id of the stream to read |
integer | timestamp | timestamp of the packet |
table | connection | connection information |
673 | function Player:writeUpdateStream(streamId, connection, dirtyMask) |
674 | if not connection:getIsServer() then |
675 | -- server code (send data to client) |
676 | local x, y, z = getTranslation(self.rootNode) |
677 | --print("SERVER ( "..tostring(self).."/"..tostring(self.controllerName).."/"..tostring(self.networkInformation.creatorConnection).." ): x/y/z="..tostring(x).." / "..tostring(y).." / "..tostring(z).." self.sendIndex="..tostring(self.networkInformation.sendIndex)) |
678 | streamWriteFloat32(streamId, x) |
679 | streamWriteFloat32(streamId, y) |
680 | streamWriteFloat32(streamId, z) |
681 | |
682 | local dx, _, dz = localDirectionToLocal(self.cameraNode, getParent(self.cameraNode), 0, 0, 1) |
683 | local alpha = math.atan2(dx, dz) |
684 | streamWriteFloat32(streamId, alpha) |
685 | |
686 | streamWriteBool(streamId, self.isObjectInRange) |
687 | if self.isObjectInRange then |
688 | streamWriteFloat32(streamId, self.lastFoundObjectMass) |
689 | end |
690 | streamWriteBool(streamId, self.isCarryingObject) |
691 | streamWriteBool(streamId, self.baseInformation.isOnGroundPhysics) |
692 | local isOwner = connection == self.networkInformation.creatorConnection |
693 | if isOwner then |
694 | streamWriteInt32(streamId, self.networkInformation.sendIndex) |
695 | -- [animation] |
696 | local isCrouching = self.baseInformation.isCrouched |
697 | streamWriteBool(streamId, isCrouching) |
698 | -- |
699 | else |
700 | streamWriteBool(streamId, self.isControlled) |
701 | -- [animation] |
702 | local isCrouching = self.baseInformation.isCrouched or self.playerStateMachine:isActive("crouch") |
703 | streamWriteBool(streamId, isCrouching) |
704 | -- |
705 | end |
706 | else |
707 | -- client code (send data to server) |
708 | if self.isOwner then |
709 | -- sending translation information to the server and reset the translations accumulated over the update() calls |
710 | streamWriteFloat32(streamId, self.networkInformation.tickTranslation[1]) |
711 | streamWriteFloat32(streamId, self.networkInformation.tickTranslation[2]) |
712 | streamWriteFloat32(streamId, self.networkInformation.tickTranslation[3]) |
713 | self.networkInformation.tickTranslation[1] = 0.0 |
714 | self.networkInformation.tickTranslation[2] = 0.0 |
715 | self.networkInformation.tickTranslation[3] = 0.0 |
716 | local x, y, z, w = getQuaternion(self.cameraNode) |
717 | streamWriteFloat32(streamId, x) -- ? ToDo: Utils.writeCompressedQuaternion() |
718 | streamWriteFloat32(streamId, y) |
719 | streamWriteFloat32(streamId, z) |
720 | streamWriteFloat32(streamId, w) |
721 | |
722 | streamWriteInt32(streamId, self.networkInformation.index) |
723 | streamWriteBool(streamId, self.isControlled) |
724 | -- [animation] |
725 | local isCrouching = self.playerStateMachine:isActive("crouch") |
726 | streamWriteBool(streamId, isCrouching) |
727 | -- |
728 | if self.isCarryingObject then |
729 | streamWriteBool(streamId, self.networkInformation.rotateObject) |
730 | if self.networkInformation.rotateObject then |
731 | streamWriteFloat32(streamId, self.networkInformation.rotateObjectInputH) |
732 | streamWriteFloat32(streamId, self.networkInformation.rotateObjectInputV) |
733 | end |
734 | end |
735 | end |
736 | end |
737 | end |