Script v1.7.1.0
- AI
- Animals
- Contracts
- Debug
- Economy
- Effects
- Events
- Farms
- GUI
- Handtools
- I3d
- Materials
- Misc
- Objects
- Placeables
- Player
- Player
- PlayerModelManager
- PlayerPickUpObjectEvent
- PlayerSetFarmAnswerEvent
- PlayerSetFarmEvent
- PlayerSetHandToolEvent
- PlayerStateActivateObject
- PlayerStateAnimalFeed
- PlayerStateAnimalInteract
- PlayerStateAnimalPet
- PlayerStateAnimalRide
- PlayerStateBase
- PlayerStateCrouch
- PlayerStateCycleHandtool
- PlayerStateDrop
- PlayerStateFall
- PlayerStateIdle
- PlayerStateJump
- PlayerStateMachine
- PlayerStatePickup
- PlayerStateRun
- PlayerStateSwim
- PlayerStateThrow
- PlayerStateUseLight
- PlayerStateWalk
- PlayerStyle
- PlayerSwitchedFarmEvent
- PlayerTeleportEvent
- PlayerThrowObjectEvent
- PlayerToggleLightEvent
- Shop
- Sounds
- Specializations
- Triggers
- Utils
- Vehicles
- Weather
Engine v1.7.1.0
- AI
- Animation
- Camera
- Entity
- Fillplanes
- General
- I3D
- Input
- Lighting
- Math
- Network
- Node
- Overlays
- Particle System
- Physics
- Rendering
- Scenegraph
- Shape
- Sound
- Spline
- String
- Terrain Detail
- Text Rendering
- Tire Track
- XML
- general
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.firstPerson#cutFocusOffset | offset for the focus of the chainsaw cut (in m) |
player.character.firstPerson#cutFocusRotation | rotation for the focus of the chainsaw cut (in deg) |
player.character.firstPerson#minCutDistance | minimum distance for the chainsaw cutting (in m) |
player.character.firstPerson#maxCutDistance | maximum distance for the chainsaw cutting (in m) |
player.character.firstPerson#cutDetectionDistance | distance to detect a cut for the chainsaw (in m) |
player.character.firstPerson#cuttingCameraNode | scenegraph node for the chainsaw camera |
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
- calculate2DDotProductAgainstVelocity
- cameraBob
- checkObjectInRange
- consoleCommandReloadIKChains
- consoleCommandToggleFlightAndNoHUDMode
- consoleCommandTogglePlayerDebug
- consoleCommandToggleSuperStrongMode
- consoleCommandToggleWoodCuttingMaker
- debugDraw
- delete
- deleteHandToolStopSample
- deleteStartleAnimalData
- deleteStartleAnimalSound
- deleteVisuals
- draw
- drawUIInfo
- equipHandtool
- getDesiredSpeed
- getEquippedHandtoolFilename
- getIsInputAllowed
- getParentComponent
- getPositionData
- getUpdatePriority
- groundRaycastCallback
- hasHandtoolEquipped
- load
- loadHandTool
- loadHandToolStopSample
- loadVisuals
- 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
- playHandToolStopSample
- readStream
- readUpdateStream
- recordPositionInformation
- registerActionEvents
- removeActionEvents
- resetBrake
- resetCameraInputsInformation
- resetInputsInformation
- rotateObject
- setCuttingAnim
- setIKDirty
- setLightIsActive
- setRotation
- setVisibility
- setWalkingLock
- setWoodWorkVisibility
- testScope
- throwObject
- unequipHandtool
- update
- updateActionEvents
- updateAnimationParameters
- updateFX
- updateInterpolation
- updateInterpolationTick
- updateKinematic
- updateNetworkMovementHistory
- updatePlayerStates
- updatePlayHandToolStopSample
- updateRotation
- updateSound
- updateTick
- updateWaterParms
- writeStream
- writeUpdateStream
calculate2DDotProductAgainstVelocity
DescriptionDefinitioncalculate2DDotProductAgainstVelocity()Code
2688 | function Player:calculate2DDotProductAgainstVelocity(velocity, currentSpeed, vector) |
2689 | local normalizedVelX = velocity[1] / currentSpeed |
2690 | local normalizedVelZ = velocity[3] / currentSpeed |
2691 | local vectorMagnitude = math.sqrt(vector[1] * vector[1] + vector[3] * vector[3]) |
2692 | local normalizedVectorX = vector[1] / vectorMagnitude |
2693 | local normalizedVectorZ = vector[3] / vectorMagnitude |
2694 | local dot = normalizedVelX * normalizedVectorX + normalizedVelZ * normalizedVectorZ |
2695 | |
2696 | return dot |
2697 | end |
cameraBob
DescriptionFor waterDefinition
cameraBob()Code
2514 | function Player:cameraBob(dt) |
2515 | local amplitude = 0.0 |
2516 | local isSwimming = self.playerStateMachine:isActive("swim") |
2517 | local isWalking = self.playerStateMachine:isActive("walk") |
2518 | local isCrouching = self.playerStateMachine:isActive("crouch") |
2519 | local isRunning = self.playerStateMachine:isActive("run") |
2520 | local targetCameraOffset = 0.0 |
2521 | local dtInSec = dt * 0.001 |
2522 | |
2523 | if isSwimming then |
2524 | amplitude = 0.045 |
2525 | targetCameraOffset = self.baseInformation.waterCameraOffset |
2526 | elseif isCrouching then |
2527 | amplitude = 0.045 |
2528 | elseif isWalking or isRunning then |
2529 | amplitude = 0.025 |
2530 | end |
2531 | |
2532 | if self.baseInformation.currentWaterCameraOffset ~= targetCameraOffset then |
2533 | local deltaOffset = targetCameraOffset - self.baseInformation.currentWaterCameraOffset |
2534 | if math.abs(deltaOffset) > 0.001 then |
2535 | self.baseInformation.currentWaterCameraOffset = self.baseInformation.currentWaterCameraOffset + deltaOffset * dtInSec / 0.75 |
2536 | else |
2537 | self.baseInformation.currentWaterCameraOffset = self.baseInformation.currentWaterCameraOffset + deltaOffset |
2538 | end |
2539 | if math.abs(targetCameraOffset) > 0.001 then |
2540 | self.baseInformation.currentWaterCameraOffset = MathUtil.clamp(self.baseInformation.currentWaterCameraOffset, 0, targetCameraOffset) |
2541 | else |
2542 | self.baseInformation.currentWaterCameraOffset = math.max(self.baseInformation.currentWaterCameraOffset, 0) |
2543 | end |
2544 | end |
2545 | |
2546 | local delta = 0.0 |
2547 | if amplitude ~= 0.0 then |
2548 | local actualSpeed = self.motionInformation.currentCoveredGroundDistance / dtInSec |
2549 | local dtInSecClamped = math.min(dtInSec, 0.06) |
2550 | local timeOffset, amplitudeScale |
2551 | |
2552 | if isSwimming then |
2553 | timeOffset = math.min(math.max(self.motionInformation.currentCoveredGroundDistance * 1.0, 0.6 * dtInSecClamped), 3.0 * dtInSecClamped * 1.0) |
2554 | amplitudeScale = math.min(math.max(actualSpeed / 3.0, 0.5), 1.0) |
2555 | else |
2556 | timeOffset = math.min(self.motionInformation.currentCoveredGroundDistance, 3.0 * dtInSecClamped) * 3.0 |
2557 | amplitudeScale = math.min(actualSpeed / 3.0, 1.0) |
2558 | end |
2559 | |
2560 | self.baseInformation.headBobTime = self.baseInformation.headBobTime + timeOffset |
2561 | amplitudeScale = (self.baseInformation.lastCameraAmplitudeScale + amplitudeScale) * 0.5 |
2562 | delta = amplitudeScale * amplitude * math.sin(self.baseInformation.headBobTime) + self.baseInformation.currentWaterCameraOffset |
2563 | self.baseInformation.lastCameraAmplitudeScale = amplitudeScale |
2564 | else |
2565 | delta = self.baseInformation.currentWaterCameraOffset |
2566 | end |
2567 | local cameraY = self.camY |
2568 | local currentCamX, _, currentCamZ = getTranslation(self.cameraNode) |
2569 | |
2570 | if not isCrouching then |
2571 | setTranslation(self.cameraNode, currentCamX, cameraY + delta, currentCamZ) |
2572 | else |
2573 | local crouchState = self.playerStateMachine:getState("crouch") |
2574 | local crouchCamY = crouchState.crouchCameraY |
2575 | setTranslation(self.cameraNode, currentCamX, crouchCamY + delta, currentCamZ) |
2576 | end |
2577 | end |
checkObjectInRange
DescriptionDefinitioncheckObjectInRange()Code
1213 | function Player:checkObjectInRange() |
1214 | -- handle picking up of objects |
1215 | if self.isControlled then |
1216 | if self.isServer then |
1217 | if not self.isCarryingObject then |
1218 | local x,y,z = localToWorld(self.cameraNode, 0,0,1.0) |
1219 | local dx,dy,dz = localDirectionToWorld(self.cameraNode, 0,0,-1) |
1220 | self.lastFoundObject = nil |
1221 | self.lastFoundObjectHitPoint = nil |
1222 | raycastAll(x,y,z, dx,dy,dz, "pickUpObjectRaycastCallback", Player.MAX_PICKABLE_OBJECT_DISTANCE, self) |
1223 | self.isObjectInRange = self.lastFoundObject ~= nil |
1224 | else |
1225 | -- check if object still exists |
1226 | if self.pickedUpObject ~= nil then |
1227 | if not entityExists(self.pickedUpObject) then |
1228 | Player.PICKED_UP_OBJECTS[self.pickedUpObject] = false |
1229 | self.pickedUpObject = nil |
1230 | self.pickedUpObjectJointId = nil |
1231 | self.isCarryingObject = false |
1232 | end |
1233 | end |
1234 | end |
1235 | end |
1236 | end |
1237 | 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 |
1947 | function Player.consoleCommandReloadIKChains(unusedSelf) |
1948 | local xmlFile = loadXMLFile("TempXML", g_currentMission.player.xmlFilename) |
1949 | |
1950 | local i = 0 |
1951 | while true do |
1952 | local key = string.format("player.ikChains.ikChain(%d)", i) |
1953 | if not hasXMLProperty(xmlFile, key) then |
1954 | break |
1955 | end |
1956 | |
1957 | local id = getXMLString(xmlFile, key.. "#id") |
1958 | local chain = g_currentMission.player.ikChains[id] |
1959 | if chain ~= nil then |
1960 | for k, node in pairs(chain.nodes) do |
1961 | local nodeKey = key..string.format(".node(%d)", k - 1) |
1962 | node.minRx = math.rad(Utils.getNoNil(getXMLFloat(xmlFile, nodeKey .. "#minRx"), -180)) |
1963 | node.maxRx = math.rad(Utils.getNoNil(getXMLFloat(xmlFile, nodeKey .. "#maxRx"), 180)) |
1964 | node.minRy = math.rad(Utils.getNoNil(getXMLFloat(xmlFile, nodeKey .. "#minRy"), -180)) |
1965 | node.maxRy = math.rad(Utils.getNoNil(getXMLFloat(xmlFile, nodeKey .. "#maxRy"), 180)) |
1966 | node.minRz = math.rad(Utils.getNoNil(getXMLFloat(xmlFile, nodeKey .. "#minRz"), -180)) |
1967 | node.maxRz = math.rad(Utils.getNoNil(getXMLFloat(xmlFile, nodeKey .. "#maxRz"), 180)) |
1968 | node.damping = math.rad(Utils.getNoNil(getXMLFloat(xmlFile, nodeKey .. "#damping"), 0)) |
1969 | |
1970 | chain.ikChainSolver:setJointTransformGroup(k - 1, node.node, node.minRx, node.maxRx, node.minRy, node.maxRy, node.minRz, node.maxRz, node.damping) |
1971 | end |
1972 | end |
1973 | i = i + 1 |
1974 | end |
1975 | |
1976 | g_currentMission.player:setIKDirty() |
1977 | |
1978 | delete(xmlFile) |
1979 | end |
consoleCommandToggleFlightAndNoHUDMode
DescriptionToggle flight modeDefinition
consoleCommandToggleFlightAndNoHUDMode()Return Values
string | that | will be displayed on console |
1891 | function Player:consoleCommandToggleFlightAndNoHUDMode() |
1892 | g_flightAndNoHUDKeysEnabled = not g_flightAndNoHUDKeysEnabled |
1893 | if not g_flightAndNoHUDKeysEnabled then |
1894 | self.debugFlightMode = false -- force reset flight mode |
1895 | end |
1896 | |
1897 | return "PlayerFlightAndNoHUDMode = " .. tostring(g_flightAndNoHUDKeysEnabled) |
1898 | end |
consoleCommandTogglePlayerDebug
DescriptionToggle player debug info displayDefinition
consoleCommandTogglePlayerDebug()Return Values
string | that | will be displayed on console |
2809 | function Player:consoleCommandTogglePlayerDebug() |
2810 | self.baseInformation.isInDebug = not self.baseInformation.isInDebug |
2811 | return "Player Debug = " .. tostring(self.baseInformation.isInDebug) |
2812 | end |
consoleCommandToggleSuperStrongMode
DescriptionToggle super-strength modeDefinition
consoleCommandToggleSuperStrongMode()Code
1911 | function Player:consoleCommandToggleSuperStrongMode() |
1912 | if self.superStrengthEnabled then |
1913 | self.superStrengthEnabled = false |
1914 | Player.MAX_PICKABLE_OBJECT_MASS = 0.2 |
1915 | return "Player now has normal strength" |
1916 | else |
1917 | self.superStrengthEnabled = true |
1918 | Player.MAX_PICKABLE_OBJECT_MASS = 25 |
1919 | return "Player now has super-strength" |
1920 | end |
1921 | end |
consoleCommandToggleWoodCuttingMaker
DescriptionToggle wood cutting markerDefinition
consoleCommandToggleWoodCuttingMaker(table unusedSelf)Arguments
table | unusedSelf | unused parameter |
string | that | will be displayed on console |
1904 | function Player.consoleCommandToggleWoodCuttingMaker(unusedSelf) |
1905 | g_woodCuttingMarkerEnabled = not g_woodCuttingMarkerEnabled |
1906 | return "WoodCuttingMarker = " .. tostring(g_woodCuttingMarkerEnabled) |
1907 | end |
debugDraw
DescriptionPrints player debug information regarding motion and input.Definition
debugDraw()Code
2598 | function Player:debugDraw() |
2599 | if (self.baseInformation.isInDebug) then |
2600 | setTextColor(1, 0, 0, 1) |
2601 | local line = 0.96 |
2602 | renderText(0.05, line, 0.02, "[motion]") line = line - 0.02 |
2603 | renderText(0.05, line, 0.02, string.format("isOnGround(%s) ", tostring(self.baseInformation.isOnGround))) line = line - 0.02 |
2604 | renderText(0.05, line, 0.02, string.format("lastPosition(%3.4f, %3.4f)", self.baseInformation.lastPositionX, self.baseInformation.lastPositionZ)) line = line - 0.02 |
2605 | renderText(0.05, line, 0.02, string.format("distanceCovered(%.2f)", self.motionInformation.coveredGroundDistance)) line = line - 0.02 |
2606 | renderText(0.05, line, 0.02, string.format("inWater(%s)", tostring(self.baseInformation.isInWater))) line = line - 0.02 |
2607 | renderText(0.05, line, 0.02, string.format("currentSpeed(%.3f) speedY(%.3f)", self.motionInformation.currentSpeed, self.motionInformation.currentSpeedY)) line = line - 0.02 |
2608 | |
2609 | setTextColor(0, 1, 0, 1) |
2610 | line = line - 0.02 |
2611 | renderText(0.05, line, 0.02, "[input]")line = line - 0.02 |
2612 | renderText(0.05, line, 0.02, string.format("right(%3.4f)", self.inputInformation.moveRight)) |
2613 | line = line - 0.02 |
2614 | renderText(0.05, line, 0.02, string.format("forward(%3.4f)", self.inputInformation.moveForward)) |
2615 | line = line - 0.02 |
2616 | renderText(0.05, line, 0.02, string.format("pitch(%3.4f)", self.inputInformation.pitchCamera)) |
2617 | line = line - 0.02 |
2618 | renderText(0.05, line, 0.02, string.format("yaw(%3.4f)", self.inputInformation.yawCamera)) |
2619 | line = line - 0.02 |
2620 | renderText(0.05, line, 0.02, string.format("runAxis(%3.4f)", self.inputInformation.runAxis)) |
2621 | line = line - 0.02 |
2622 | renderText(0.05, line, 0.02, string.format("crouchState(%s)", tostring(self.inputInformation.crouchState))) |
2623 | line = line - 0.02 |
2624 | renderText(0.05, line, 0.02, string.format("interactState(%s)", tostring(self.inputInformation.interactState))) |
2625 | line = line - 0.02 |
2626 | end |
2627 | end |
delete
DescriptionDeleteDefinition
delete()Code
689 | function Player:delete() |
690 | if self.isOwner then -- only remove action events if this Player instance was controller by the current user |
691 | g_messageCenter:unsubscribeAll(self) |
692 | self:removeActionEvents() |
693 | end |
694 | |
695 | if self.isCarryingObject then |
696 | if g_server ~= nil then |
697 | self:pickUpObject(false) |
698 | end |
699 | end |
700 | |
701 | if self.pickedUpObjectOverlay ~= nil then |
702 | self.pickedUpObjectOverlay:delete() |
703 | end |
704 | |
705 | if self:hasHandtoolEquipped() then |
706 | self.baseInformation.currentHandtool:onDeactivate() |
707 | self.baseInformation.currentHandtool:delete() |
708 | self.baseInformation.currentHandtool = nil |
709 | end |
710 | -- @note: chainsaw stop sounds needs to be deleted afterwards |
711 | for _, sample in pairs(self.soundInformation.samples) do |
712 | g_soundManager:deleteSample(sample) |
713 | end |
714 | g_soundManager:deleteSamples(self.soundInformation.surfaceSounds) |
715 | |
716 | if self.animationInformation.player ~= 0 then |
717 | delete(self.animationInformation.player) |
718 | self.animationInformation.player = 0 |
719 | end |
720 | Player.deleteVisuals(self, self.ikChains) |
721 | removeCCT(self.controllerIndex) |
722 | delete(self.rootNode) |
723 | self.playerStateMachine:delete() |
724 | self:deleteStartleAnimalData() |
725 | self.lightNode = nil |
726 | if self.foliageBendingId ~= nil then |
727 | g_currentMission.foliageBendingSystem:destroyObject(self.foliageBendingId) |
728 | self.foliageBendingId = nil |
729 | end |
730 | |
731 | if self.isOwner then |
732 | removeConsoleCommand("gsToggleFlightAndNoHUDMode") |
733 | removeConsoleCommand("gsToggleWoodCuttingMaker") |
734 | removeConsoleCommand("gsTogglePlayerDebug") |
735 | removeConsoleCommand("gsReloadIKChains") |
736 | removeConsoleCommand("gsToggleSuperStrength") |
737 | end |
738 | |
739 | Player:superClass().delete(self) |
740 | end |
deleteHandToolStopSample
DescriptionDefinitiondeleteHandToolStopSample()Code
2271 | function Player:deleteHandToolStopSample() |
2272 | if self.soundInformation.samples.handtoolStop.soundSample ~= nil then |
2273 | g_soundManager:deleteSample(self.soundInformation.samples.handtoolStop) |
2274 | self.soundInformation.samples.handtoolStop = {} |
2275 | self.soundInformation.deleteHandtoolStopSampleAfterPlay = false |
2276 | end |
2277 | end |
deleteStartleAnimalData
DescriptionRemove animal sound timer and sound itself (deprecated?)Definition
deleteStartleAnimalData()Code
1925 | function Player:deleteStartleAnimalData() |
1926 | if (self.startleAnimalSoundTimerId) then |
1927 | removeTimer(self.startleAnimalSoundTimerId) |
1928 | self.startleAnimalSoundTimerId = nil |
1929 | end |
1930 | self:deleteStartleAnimalSound() |
1931 | end |
deleteStartleAnimalSound
DescriptionRemove animal sound(deprecated?)Definition
deleteStartleAnimalSound()Code
1935 | function Player:deleteStartleAnimalSound() |
1936 | if (self.startleAnimalSoundNode) then |
1937 | delete(self.startleAnimalSoundNode) |
1938 | self.startleAnimalSoundNode = nil |
1939 | end |
1940 | self.startleAnimalSoundTimerId = nil |
1941 | end |
deleteVisuals
DescriptionDelete visual information for the playerDefinition
deleteVisuals(table self, table ikChains)Arguments
table | self | player object for unloading the visuals |
table | ikChains | list of IK chains |
636 | function Player.deleteVisuals(self, ikChains) |
637 | if self.filename ~= nil then |
638 | --- |
639 | -- fix for: WARNING: COLLISION MESH FOR 'kinematicHelper' IS BEING COOKED AT RUNTIME - THIS WILL NOT WORK ON CONSOLES |
640 | -- local isPlayer = string.match(self.xmlFilename, "player") |
641 | -- g_i3DManager:releaseSharedI3DFile(self.filename, nil, isPlayer) |
642 | -- |
643 | g_i3DManager:releaseSharedI3DFile(self.filename, nil, false) |
644 | self.filename = nil |
645 | end |
646 | for chainId, _ in pairs(ikChains) do |
647 | IKUtil.deleteIKChain(ikChains, chainId) |
648 | end |
649 | |
650 | if self.particleSystemsInformation ~= nil then |
651 | if self.particleSystemsInformation.swimNode ~= nil then |
652 | delete(self.particleSystemsInformation.swimNode) |
653 | end |
654 | if self.particleSystemsInformation.plungeNode ~= nil then |
655 | delete(self.particleSystemsInformation.plungeNode) |
656 | end |
657 | |
658 | ParticleUtil.deleteParticleSystem(self.particleSystemsInformation.systems.swim) |
659 | ParticleUtil.deleteParticleSystem(self.particleSystemsInformation.systems.plunge) |
660 | end |
661 | |
662 | self.visualInformation:unlinkProtectiveWear() |
663 | |
664 | if self.thirdPersonSpineNode ~= nil then |
665 | delete(self.thirdPersonSpineNode) |
666 | self.thirdPersonSpineNode = nil |
667 | end |
668 | if self.skeletonThirdPerson ~= nil then |
669 | delete(self.skeletonThirdPerson) |
670 | self.skeletonThirdPerson = nil |
671 | end |
672 | if self.meshThirdPerson ~= nil then |
673 | delete(self.meshThirdPerson) |
674 | self.meshThirdPerson = nil |
675 | end |
676 | if self.graphicsRootNode ~= nil then |
677 | delete(self.graphicsRootNode) |
678 | self.graphicsRootNode = nil |
679 | end |
680 | end |
draw
DescriptionDraws overlay informationDefinition
draw()Code
1690 | function Player:draw() |
1691 | if self:getIsInputAllowed() then |
1692 | if self:hasHandtoolEquipped() then |
1693 | self.baseInformation.currentHandtool:draw() |
1694 | elseif not self.isCarryingObject and self.isObjectInRange and not self:hasHandtoolEquipped() then |
1695 | if not g_flightAndNoHUDKeysEnabled and self.pickedUpObjectOverlay ~= nil then |
1696 | self.pickedUpObjectOverlay:setDimension(self.pickedUpObjectWidth, self.pickedUpObjectHeight) |
1697 | self.pickedUpObjectOverlay:setUVs(self.pickedUpObjectHandUVs) |
1698 | self.pickedUpObjectOverlay:render() |
1699 | end |
1700 | elseif not g_flightAndNoHUDKeysEnabled and self.pickedUpObjectOverlay ~= nil then |
1701 | self.pickedUpObjectOverlay:setDimension(self.pickedUpObjectAimingWidth, self.pickedUpObjectAimingHeight) |
1702 | self.pickedUpObjectOverlay:setUVs(self.pickedUpObjectAimingUVs) |
1703 | self.pickedUpObjectOverlay:render() |
1704 | end |
1705 | end |
1706 | end |
drawUIInfo
DescriptionRenders UI information for the playerDefinition
drawUIInfo()Code
1671 | function Player:drawUIInfo() |
1672 | if self.isClient and self.isControlled and not self.isEntered then |
1673 | if not g_gui:getIsGuiVisible() and not g_flightAndNoHUDKeysEnabled then |
1674 | local x, y, z = getTranslation(self.graphicsRootNode) |
1675 | local x1, y1, z1 = getWorldTranslation(getCamera()) |
1676 | local diffX = x - x1 |
1677 | local diffY = y - y1 |
1678 | local diffZ = z - z1 |
1679 | local dist = MathUtil.vector3LengthSq(diffX, diffY, diffZ) |
1680 | if dist <= 100 * 100 then |
1681 | y = y + self.baseInformation.tagOffset[2] |
1682 | Utils.renderTextAtWorldPosition(x, y, z, self.visualInformation.playerName, getCorrectTextSize(0.02), 0) |
1683 | end |
1684 | end |
1685 | end |
1686 | end |
equipHandtool
DescriptionDefinitionequipHandtool()Code
2200 | function Player:equipHandtool(handtoolFilename, force, noEventSend) |
2201 | if self.isOwner then -- make sure we only change depth of field for locally controlled player instances |
2202 | if handtoolFilename == nil or handtoolFilename == "" then |
2203 | g_depthOfFieldManager:reset() |
2204 | else |
2205 | g_depthOfFieldManager:setManipulatedParams(0.8, 0.6, nil, nil, nil) |
2206 | end |
2207 | end |
2208 | |
2209 | PlayerSetHandToolEvent.sendEvent(self, handtoolFilename, force, noEventSend) |
2210 | |
2211 | if self:hasHandtoolEquipped() then |
2212 | if self.baseInformation.currentHandtool.configFileName:lower() ~= handtoolFilename:lower() or handtoolFilename == "" or force then |
2213 | self.baseInformation.currentHandtool:onDeactivate() |
2214 | self.baseInformation.currentHandtool:delete() |
2215 | self.baseInformation.currentHandtool = nil |
2216 | end |
2217 | if handtoolFilename ~= "" then |
2218 | self.baseInformation.currentHandtool = self:loadHandTool(handtoolFilename) |
2219 | end |
2220 | else |
2221 | if handtoolFilename ~= "" then |
2222 | self.baseInformation.currentHandtool = self:loadHandTool(handtoolFilename) |
2223 | end |
2224 | end |
2225 | -- if we have loaded a handtool, then we configure it |
2226 | if self:hasHandtoolEquipped() then |
2227 | self.baseInformation.currentHandtool:onActivate(self:getIsInputAllowed()) |
2228 | self.baseInformation.currentHandtool:setHandNode(self.rightArmToolNode) |
2229 | |
2230 | local ikTargets = self.baseInformation.currentHandtool.targets |
2231 | if ikTargets ~= nil then |
2232 | for ikChainId, target in pairs(ikTargets) do |
2233 | IKUtil.setTarget(self.ikChains, ikChainId, target) |
2234 | end |
2235 | self:setIKDirty() |
2236 | end |
2237 | end |
2238 | end |
getDesiredSpeed
DescriptionDefinitiongetDesiredSpeed()Code
2631 | function Player:getDesiredSpeed() |
2632 | local inputRight = self.inputInformation.moveRight |
2633 | local inputForward = self.inputInformation.moveForward |
2634 | |
2635 | if ((inputForward ~= 0.0) or (inputRight ~= 0.0)) then |
2636 | local isSwimming = self.playerStateMachine:isActive("swim") |
2637 | local isCrouching = self.playerStateMachine:isActive("crouch") |
2638 | local isFalling = self.playerStateMachine:isActive("fall") |
2639 | local isUsingHandtool = self:hasHandtoolEquipped() |
2640 | local baseSpeed = self.motionInformation.maxWalkingSpeed |
2641 | local runningSpeed = 0 |
2642 | if isFalling then |
2643 | baseSpeed = self.motionInformation.maxFallingSpeed |
2644 | elseif isSwimming then |
2645 | baseSpeed = self.motionInformation.maxSwimmingSpeed |
2646 | elseif isCrouching then |
2647 | baseSpeed = self.motionInformation.maxCrouchingSpeed |
2648 | end |
2649 | |
2650 | local magnitude = math.sqrt(inputRight * inputRight + inputForward * inputForward) |
2651 | local desiredSpeed = MathUtil.clamp(magnitude, 0.0, 1.0) * baseSpeed |
2652 | local inputRun = self.inputInformation.runAxis |
2653 | |
2654 | if (inputRun > 0.0) and not (isSwimming or isCrouching or isUsingHandtool) then -- check if we are running |
2655 | runningSpeed = self.motionInformation.maxRunningSpeed |
2656 | |
2657 | if g_addTestCommands and not g_isPresentationVersion then |
2658 | runningSpeed = self.motionInformation.maxPresentationRunningSpeed |
2659 | elseif g_addCheatCommands and not g_isPresentationVersion and (g_currentMission.isMasterUser or g_currentMission:getIsServer()) then |
2660 | runningSpeed = self.motionInformation.maxCheatRunningSpeed |
2661 | end |
2662 | desiredSpeed = math.max(desiredSpeed + (runningSpeed - desiredSpeed) * MathUtil.clamp(inputRun, 0.0, 1.0), desiredSpeed) |
2663 | end |
2664 | return desiredSpeed |
2665 | end |
2666 | return 0.0 |
2667 | 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 |
2255 | function Player:getEquippedHandtoolFilename() |
2256 | return self.baseInformation.currentHandtool ~= nil and self.baseInformation.currentHandtool.configFileName or "" |
2257 | 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. |
1053 | function Player:getIsInputAllowed() |
1054 | return self.isEntered and self.isClient and not g_gui:getIsGuiVisible() |
1055 | 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 |
628 | function Player:getParentComponent(node) |
629 | return self.graphicsRootNode |
630 | 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 |
1549 | function Player:getPositionData() |
1550 | local posX, posY, posZ = getTranslation(self.rootNode) |
1551 | if self.isClient and self.isControlled and self.isEntered then |
1552 | return posX, posY, posZ, self.rotY |
1553 | else |
1554 | return posX, posY, posZ, self.graphicsRotY |
1555 | end |
1556 | 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 |
1878 | function Player:getUpdatePriority(skipCount, x, y, z, coeff, connection) |
1879 | if self.owner == connection then |
1880 | return 50 |
1881 | end |
1882 | local x1, y1, z1 = getTranslation(self.rootNode) |
1883 | local dist = MathUtil.vector3Length(x1 - x, y1 - y, z1 - z) |
1884 | local clipDist = self.clipDistance |
1885 | return (1 - dist / clipDist) * 0.8 + 0.5 * skipCount * 0.2 |
1886 | end |
groundRaycastCallback
DescriptionCallback used to get object below playerDefinition
groundRaycastCallback(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 |
1989 | function Player:groundRaycastCallback(hitObjectId, x, y, z, distance) |
1990 | self.belowPlayerObject = hitObjectId |
1991 | return false |
1992 | end |
hasHandtoolEquipped
DescriptionDefinitionhasHandtoolEquipped()Code
2248 | function Player:hasHandtoolEquipped() |
2249 | return self.baseInformation.currentHandtool ~= nil |
2250 | end |
load
DescriptionLoading player informationDefinition
load(string xmlFilename, string controllerName, integer playerColorIndex, table creatorConnection, bool isOwner)Arguments
string | xmlFilename | XML filename containing player information |
string | controllerName | name of the player controlling |
integer | playerColorIndex | color index of the table g_playerColors[] |
table | creatorConnection | |
bool | isOwner | true is current player is owner |
580 | function Player:load(xmlFilename, playerStyle, creatorConnection, isOwner) |
581 | self.networkInformation.creatorConnection = creatorConnection |
582 | self.isOwner = isOwner |
583 | self.rootNode = createTransformGroup("PlayerCCT") |
584 | link(getRootNode(), self.rootNode) |
585 | |
586 | self.ikChains = {} |
587 | Player.loadVisuals(self, xmlFilename, playerStyle, nil, true, self.ikChains, self.getParentComponent, self, nil) |
588 | |
589 | self.playerStateMachine:load() |
590 | |
591 | self.isObjectInRange = false |
592 | self.isCarryingObject = false |
593 | self.pickedUpObject = nil |
594 | |
595 | local uiScale = g_gameSettings:getValue("uiScale") |
596 | |
597 | -- TODO: move to HUD |
598 | self.pickedUpObjectWidth, self.pickedUpObjectHeight = getNormalizedScreenValues(80 * uiScale, 80 * uiScale) |
599 | self.pickedUpObjectOverlay = Overlay:new(g_baseHUDFilename, 0.5, 0.5, self.pickedUpObjectWidth, self.pickedUpObjectHeight) |
600 | self.pickedUpObjectOverlay:setAlignment(Overlay.ALIGN_VERTICAL_MIDDLE, Overlay.ALIGN_HORIZONTAL_CENTER) |
601 | self.pickedUpObjectHandUVs = getNormalizedUVs{0, 138, 80, 80} |
602 | self.pickedUpObjectAimingUVs = getNormalizedUVs{0, 48, 48, 48} |
603 | self.pickedUpObjectAimingWidth, self.pickedUpObjectAimingHeight = getNormalizedScreenValues(20 * uiScale, 20 * uiScale) |
604 | self.pickedUpObjectOverlay:setUVs(self.pickedUpObjectAimingUVs) |
605 | self.pickedUpObjectOverlay:setColor(1, 1, 1, 0.3) |
606 | |
607 | self:moveToAbsoluteInternal(0, -200, 0) |
608 | |
609 | self.controllerIndex = createCCT(self.rootNode, self.baseInformation.capsuleRadius, self.baseInformation.capsuleHeight, 0.6, 45.0, 0.1, Player.kinematicCollisionMask, self.motionInformation.mass) |
610 | |
611 | self.lockedInput = false |
612 | |
613 | if self.isOwner then |
614 | addConsoleCommand("gsToggleFlightAndNoHUDMode", "Enables/disables the flight (J) and no HUD (O) toggle keys", "consoleCommandToggleFlightAndNoHUDMode", self) |
615 | addConsoleCommand("gsToggleWoodCuttingMaker", "Enables/disables chainsaw woodcutting marker", "Player.consoleCommandToggleWoodCuttingMaker", nil) |
616 | addConsoleCommand("gsTogglePlayerDebug", "Enables/disables player debug information", "consoleCommandTogglePlayerDebug", self) |
617 | if g_addTestCommands then |
618 | addConsoleCommand("gsReloadIKChains", "Reloads IKChains", "Player.consoleCommandReloadIKChains", nil) |
619 | addConsoleCommand("gsToggleSuperStrength", "Enables/disables player super strength", "consoleCommandToggleSuperStrongMode", self) |
620 | end |
621 | end |
622 | end |
loadHandTool
DescriptionLoading hand tools for the playerDefinition
loadHandTool(string xmlFilename)Arguments
string | xmlFilename | XML filename |
table | returns | the handtool |
2158 | function Player:loadHandTool(xmlFilename) |
2159 | if GS_IS_CONSOLE_VERSION and not fileExists(xmlFilename) then |
2160 | return nil |
2161 | end |
2162 | local dataStoreItem = g_storeManager:getItemByXMLFilename(xmlFilename) |
2163 | if dataStoreItem ~= nil then |
2164 | local storeItemXmlFilename = dataStoreItem.xmlFilename |
2165 | local xmlFile = loadXMLFile("TempXML", storeItemXmlFilename) |
2166 | local handToolType = getXMLString(xmlFile, "handTool.handToolType") |
2167 | delete(xmlFile) |
2168 | |
2169 | if handToolType ~= nil then |
2170 | local classObject = HandTool.handToolTypes[handToolType] |
2171 | if classObject == nil then |
2172 | local modName, _ = Utils.getModNameAndBaseDirectory(storeItemXmlFilename) |
2173 | if modName ~= nil then |
2174 | handToolType = modName.."."..handToolType |
2175 | classObject = HandTool.handToolTypes[handToolType] |
2176 | end |
2177 | end |
2178 | local handTool = nil |
2179 | if classObject ~= nil then |
2180 | handTool = classObject:new(self.isServer, self.isClient) |
2181 | else |
2182 | g_logManager:devError("Error: Invalid handtool type '%s'", handToolType) |
2183 | end |
2184 | if handTool ~= nil then |
2185 | if not handTool:load(storeItemXmlFilename, self) then |
2186 | g_logManager:devError("Error: Failed to load handtool '%s'", storeItemXmlFilename) |
2187 | handTool:delete() |
2188 | handTool = nil |
2189 | end |
2190 | end |
2191 | |
2192 | return handTool |
2193 | end |
2194 | end |
2195 | return nil |
2196 | end |
loadHandToolStopSample
DescriptionDefinitionloadHandToolStopSample()Code
2261 | function Player:loadHandToolStopSample(xmlFile, xmlPath, xmlNode) |
2262 | if self.soundInformation.samples.handtoolStop.soundSample ~= nil then |
2263 | self:deleteHandToolStopSample() |
2264 | end |
2265 | local sample = g_soundManager:loadSampleFromXML(xmlFile, xmlPath, xmlNode, self.baseDirectory, self.rightArmToolNode, 1, AudioGroup.VEHICLE, nil, nil) |
2266 | self.soundInformation.samples.handtoolStop = sample |
2267 | end |
loadVisuals
DescriptionLoading visuals for the playerDefinition
loadVisuals(table self, string xmlFilename, table playerStyle, table linkNode, bool isRealPlayer, table ikChains, function getParentFunc, function getParentFuncTarget, table parentObj)Arguments
table | self | player object for loading the visuals |
string | xmlFilename | XML filename |
table | playerStyle | |
table | linkNode | node to link the third person skeleton of the player on |
bool | isRealPlayer | false if player is in a vehicle |
table | ikChains | list of IK chains |
function | getParentFunc | |
function | getParentFuncTarget | |
table | parentObj | parent object |
bool | true | if ok |
291 | function Player.loadVisuals(self, xmlFilename, playerStyle, linkNode, isRealPlayer, ikChains, getParentFunc, getParentFuncTarget, parentObj) |
292 | self.xmlFilename = xmlFilename |
293 | self.customEnvironment, self.baseDirectory = Utils.getModNameAndBaseDirectory(xmlFilename) |
294 | local xmlFile = loadXMLFile("TempXML", xmlFilename) |
295 | if xmlFile == 0 then |
296 | return false |
297 | end |
298 | |
299 | local filename = getXMLString(xmlFile, "player.filename") |
300 | self.filename = Utils.getFilename(filename, self.baseDirectory) |
301 | local rootNode = g_i3DManager:loadSharedI3DFile(self.filename, nil, nil, true) |
302 | |
303 | self.graphicsRootNode = createTransformGroup("player_graphicsRootNode") |
304 | |
305 | if isRealPlayer then |
306 | self.cameraNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.camera#index")) |
307 | if self.cameraNode == nil then |
308 | g_logManager:devError("Error: Failed to find player camera in '%s'", self.filename) |
309 | end |
310 | self.camX, self.camY, self.camZ = getTranslation(self.cameraNode) |
311 | setNearClip(self.cameraNode, 0.15) -- lessens night light windows flickering (standard value: 0.1) |
312 | setFarClip(self.cameraNode, 6000) -- prevents distance mountains from clipping (standard value: 5000) |
313 | self.fovY = calculateFovY(self.cameraNode) |
314 | setFovY(self.cameraNode, self.fovY) |
315 | |
316 | self.animRootThirdPerson = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.character.thirdPerson#animRootNode")) |
317 | if self.animRootThirdPerson == nil then |
318 | g_logManager:devError("Error: Failed to find animation root node in '%s'", self.filename) |
319 | end |
320 | |
321 | -- Capsule information |
322 | self.baseInformation.capsuleHeight = getXMLFloat(xmlFile, "player.character#physicsCapsuleHeight") |
323 | self.baseInformation.capsuleRadius = getXMLFloat(xmlFile, "player.character#physicsCapsuleRadius") |
324 | self.baseInformation.capsuleTotalHeight = self.baseInformation.capsuleHeight + 2.0 * self.baseInformation.capsuleRadius |
325 | |
326 | -- first person view |
327 | self.cuttingCameraNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.character.firstPerson#cuttingCameraNode")) |
328 | setNearClip(self.cuttingCameraNode, 0.15) |
329 | setFarClip(self.cuttingCameraNode, 6000) |
330 | self.fovY = calculateFovY(self.cuttingCameraNode) |
331 | setFovY(self.cuttingCameraNode, self.fovY) |
332 | end |
333 | |
334 | -- Avator customization |
335 | self.visualInformation = PlayerStyle:new() |
336 | self.visualInformation:copySelection(playerStyle) |
337 | self.visualInformation:loadXML(self, rootNode, xmlFile, "player.character") |
338 | |
339 | self.skeletonThirdPerson = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.character.thirdPerson#skeleton")) |
340 | |
341 | if self.skeletonThirdPerson == nil then |
342 | g_logManager:devError("Error: Failed to find skeleton root node in '%s'", self.filename) |
343 | end |
344 | |
345 | self.meshThirdPerson = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.character.thirdPerson#mesh")) |
346 | |
347 | if self.meshThirdPerson == nil then |
348 | g_logManager:devError("Error: Failed to find player mesh in '%s'", self.filename) |
349 | end |
350 | |
351 | if self.meshThirdPerson ~= nil then |
352 | setVisibility(self.meshThirdPerson, false) |
353 | setClipDistance(self.meshThirdPerson, 200) |
354 | end |
355 | |
356 | self.thirdPersonSpineNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.character.thirdPerson#spine")) |
357 | self.thirdPersonSuspensionNode = Utils.getNoNil(I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.character.thirdPerson#suspension")), self.thirdPersonSpineNode) |
358 | self.thirdPersonRightHandNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.character.thirdPerson#rightHandNode")) |
359 | self.thirdPersonLeftHandNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.character.thirdPerson#leftHandNode")) |
360 | self.thirdPersonHeadNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.character.thirdPerson#headNode")) |
361 | |
362 | self.lightNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.light#index")) |
363 | if self.lightNode ~= nil then |
364 | setVisibility(self.lightNode, false) |
365 | end |
366 | |
367 | self.pickUpKinematicHelperNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.pickUpKinematicHelper#index")) |
368 | if self.pickUpKinematicHelperNode ~= nil then |
369 | self.pickUpKinematicHelperNodeChild = createTransformGroup("pickUpKinematicHelperNodeChild") |
370 | link(self.pickUpKinematicHelperNode, self.pickUpKinematicHelperNodeChild) |
371 | end |
372 | |
373 | -- IK Chains |
374 | local i = 0 |
375 | while true do |
376 | local key = string.format("player.ikChains.ikChain(%d)", i) |
377 | if not hasXMLProperty(xmlFile, key) then |
378 | break |
379 | end |
380 | IKUtil.loadIKChain(xmlFile, key, rootNode, rootNode, ikChains) |
381 | i = i + 1 |
382 | end |
383 | IKUtil.setIKChainInactive(ikChains, "spine") |
384 | if isRealPlayer then |
385 | IKUtil.deleteIKChain(ikChains, "rightFoot") |
386 | IKUtil.deleteIKChain(ikChains, "leftFoot") |
387 | IKUtil.deleteIKChain(ikChains, "rightArm") |
388 | IKUtil.deleteIKChain(ikChains, "leftArm") |
389 | IKUtil.deleteIKChain(ikChains, "spine") |
390 | end |
391 | |
392 | -- Linking: Do not use indexToObject below |
393 | if self.meshThirdPerson ~= nil then |
394 | link(getRootNode(), self.meshThirdPerson) |
395 | end |
396 | if isRealPlayer then |
397 | self.chainsawCameraFocus = createTransformGroup("player_chainsawCameraFocus") |
398 | self.chainsawSplitShapeFocus = createTransformGroup("player_chainsawSplitShapeFocus") |
399 | link(self.cameraNode, self.chainsawCameraFocus) |
400 | link(self.chainsawCameraFocus, self.chainsawSplitShapeFocus) |
401 | |
402 | local cutFocusOffset = StringUtil.getVectorNFromString(Utils.getNoNil(getXMLString(xmlFile, "player.character.firstPerson#cutFocusOffset"), "0 0 -1"), 3) |
403 | setTranslation(self.chainsawSplitShapeFocus, unpack(cutFocusOffset)) |
404 | local cutFocusRotation = StringUtil.getVectorNFromString(Utils.getNoNil(getXMLString(xmlFile, "player.character.firstPerson#cutFocusRotation"), "0 0 0"), 3) |
405 | local rotX2, rotY2, rotZ2 = unpack(cutFocusRotation) |
406 | setRotation(self.chainsawSplitShapeFocus, math.rad(rotX2), math.rad(rotY2), math.rad(rotZ2)) |
407 | self.minCutDistance = Utils.getNoNil(getXMLFloat(xmlFile, "player.character.firstPerson#minCutDistance"), 0.5) |
408 | self.maxCutDistance = Utils.getNoNil(getXMLFloat(xmlFile, "player.character.firstPerson#maxCutDistance"), 1.0) |
409 | self.cutDetectionDistance = Utils.getNoNil(getXMLFloat(xmlFile, "player.character.firstPerson#cutDetectionDistance"), 10.0) |
410 | end |
411 | |
412 | if isRealPlayer then |
413 | self.skeletonRootNode = createTransformGroup("player_skeletonRootNode") |
414 | self.foliageBendingNode = createTransformGroup("player_foliageBendingNode") |
415 | |
416 | link(getRootNode(), self.graphicsRootNode) |
417 | link(self.graphicsRootNode, self.cameraNode) |
418 | link(self.graphicsRootNode, self.skeletonRootNode) |
419 | link(self.graphicsRootNode, self.foliageBendingNode) |
420 | |
421 | if self.animRootThirdPerson ~= nil then |
422 | link(self.skeletonRootNode, self.animRootThirdPerson) |
423 | if self.skeletonThirdPerson ~= nil then |
424 | link(self.animRootThirdPerson, self.skeletonThirdPerson) |
425 | end |
426 | end |
427 | |
428 | self.visualInformation:linkProtectiveWear(self.skeletonRootNode) |
429 | |
430 | if self.skeletonThirdPerson ~= nil and getNumOfChildren(self.skeletonThirdPerson) > 0 then |
431 | local animNode = g_animCache:getNode(AnimationCache.CHARACTER) |
432 | cloneAnimCharacterSet(animNode, getParent(self.skeletonThirdPerson)) |
433 | local animCharsetId = getAnimCharacterSet(getChildAt(self.skeletonThirdPerson, 0)) |
434 | self.animationInformation.player = createConditionalAnimation() |
435 | |
436 | for key, parameter in pairs(self.animationInformation.parameters) do |
437 | conditionalAnimationRegisterParameter(self.animationInformation.player, parameter.id, parameter.type, key) |
438 | end |
439 | initConditionalAnimation(self.animationInformation.player, animCharsetId, self.xmlFilename, "player.conditionalAnimation") |
440 | setConditionalAnimationSpecificParameterIds(self.animationInformation.player, self.animationInformation.parameters.absForwardVelocity.id, self.animationInformation.parameters.yawVelocity.id) |
441 | end |
442 | |
443 | self.leftArmToolNode = createTransformGroup("leftArmToolNode") |
444 | self.rightArmToolNode = createTransformGroup("rightArmToolNode") |
445 | |
446 | if self.isOwner then |
447 | local toolRotation = StringUtil.getVectorNFromString(Utils.getNoNil(getXMLString(xmlFile, "player.character.toolNode#firstPersonRotation"), "0 0 0"), 3) |
448 | local rotX, rotY, rotZ = unpack(toolRotation) |
449 | setRotation(self.rightArmToolNode, math.rad(rotX), math.rad(rotY), math.rad(rotZ)) |
450 | local toolTranslate = StringUtil.getVectorNFromString(Utils.getNoNil(getXMLString(xmlFile, "player.character.toolNode#firstPersonTranslation"), "0 0 0"), 3) |
451 | local transX, transY, transZ = unpack(toolTranslate) |
452 | setTranslation(self.rightArmToolNode, transX, transY, transZ) |
453 | link(self.cuttingCameraNode, self.rightArmToolNode) |
454 | else |
455 | -- right |
456 | local toolRotationR = StringUtil.getVectorNFromString(Utils.getNoNil(getXMLString(xmlFile, "player.character.toolNode#thirdPersonRightNodeRotation"), "0 0 0"), 3) |
457 | local rotRX, rotRY, rotRZ = unpack(toolRotationR) |
458 | setRotation(self.rightArmToolNode, math.rad(rotRX), math.rad(rotRY), math.rad(rotRZ)) |
459 | local toolTranslateR = StringUtil.getVectorNFromString(Utils.getNoNil(getXMLString(xmlFile, "player.character.toolNode#thirdPersonRightNodeTranslation"), "0 0 0"), 3) |
460 | local transRX, transRY, transRZ = unpack(toolTranslateR) |
461 | setTranslation(self.rightArmToolNode, transRX, transRY, transRZ) |
462 | link(self.thirdPersonRightHandNode, self.rightArmToolNode) |
463 | -- left |
464 | local toolRotationL = StringUtil.getVectorNFromString(Utils.getNoNil(getXMLString(xmlFile, "player.character.toolNode#thirdPersonLeftNodeRotation"), "0 0 0"), 3) |
465 | local rotLX, rotLY, rotLZ = unpack(toolRotationL) |
466 | setRotation(self.leftArmToolNode, math.rad(rotLX), math.rad(rotLY), math.rad(rotLZ)) |
467 | local toolTranslateL = StringUtil.getVectorNFromString(Utils.getNoNil(getXMLString(xmlFile, "player.character.toolNode#thirdPersonLeftNodeTranslation"), "0 0 0"), 3) |
468 | local transLX, transLY, transLZ = unpack(toolTranslateL) |
469 | setTranslation(self.leftArmToolNode, transLX, transLY, transLZ) |
470 | link(self.thirdPersonLeftHandNode, self.leftArmToolNode) |
471 | -- light |
472 | link(self.thirdPersonHeadNode, self.lightNode) |
473 | local lightRotation = StringUtil.getVectorNFromString(Utils.getNoNil(getXMLString(xmlFile, "player.light#thirdPersonRotation"), "0 0 0"), 3) |
474 | local lightRotX, lightRotY, lightRotZ = unpack(lightRotation) |
475 | local lightTranslate = StringUtil.getVectorNFromString(Utils.getNoNil(getXMLString(xmlFile, "player.light#thirdPersonTranslation"), "0 0 0"), 3) |
476 | local lightTransX, lightTransY, lightTransZ = unpack(lightTranslate) |
477 | setRotation(self.lightNode, math.rad(lightRotX), math.rad(lightRotY), math.rad(lightRotZ)) |
478 | setTranslation(self.lightNode, lightTransX, lightTransY, lightTransZ) |
479 | end |
480 | |
481 | -- Fx |
482 | self.particleSystemsInformation.swimNode = createTransformGroup("swimFXNode") |
483 | link(getRootNode(), self.particleSystemsInformation.swimNode) |
484 | self.particleSystemsInformation.plungeNode = createTransformGroup("plungeFXNode") |
485 | link(getRootNode(), self.particleSystemsInformation.plungeNode) |
486 | |
487 | ParticleUtil.loadParticleSystem(xmlFile, self.particleSystemsInformation.systems.swim, "player.particleSystems.swim", self.particleSystemsInformation.swimNode, false, nil, self.baseDirectory) |
488 | ParticleUtil.loadParticleSystem(xmlFile, self.particleSystemsInformation.systems.plunge, "player.particleSystems.plunge", self.particleSystemsInformation.plungeNode, false, nil, self.baseDirectory) |
489 | -- |
490 | self.visualInformation:applySelection() |
491 | if self.isOwner then |
492 | self.visualInformation:setVisibility(false) |
493 | else |
494 | self.visualInformation:setVisibility(true) |
495 | end |
496 | else |
497 | link(linkNode, self.skeletonThirdPerson) |
498 | self.visualInformation:linkProtectiveWear(linkNode) |
499 | |
500 | if self.pickUpKinematicHelperNode ~= nil then |
501 | delete(self.pickUpKinematicHelperNode) |
502 | self.pickUpKinematicHelperNode = nil |
503 | end |
504 | if self.lightNode ~= nil then |
505 | delete(self.lightNode) |
506 | self.lightNode = nil |
507 | end |
508 | if self.cameraNode ~= nil then |
509 | delete(self.cameraNode) |
510 | self.cameraNode = nil |
511 | end |
512 | local offset = {localToLocal(self.thirdPersonSpineNode, self.skeletonThirdPerson, 0, 0, 0)} |
513 | |
514 | setTranslation(self.skeletonThirdPerson, -offset[1], -offset[2], -offset[3]) |
515 | self.visualInformation:applySelection() |
516 | self.visualInformation:setVisibility(true) |
517 | end |
518 | |
519 | -- Sound |
520 | if isRealPlayer then |
521 | self.soundInformation.surfaceSounds = {} |
522 | self.soundInformation.surfaceIdToSound = {} |
523 | self.soundInformation.surfaceNameToSound = {} |
524 | self.soundInformation.currentSurfaceSound = nil |
525 | |
526 | if not self.isOwner then |
527 | for _, surfaceSound in pairs(g_currentMission.surfaceSounds) do |
528 | if surfaceSound.type == "footstep" and surfaceSound.sample ~= nil then |
529 | local sample = g_soundManager:cloneSample(surfaceSound.sample, self.rootNode, self) |
530 | sample.sampleName = surfaceSound.name |
531 | |
532 | table.insert(self.soundInformation.surfaceSounds, sample) |
533 | self.soundInformation.surfaceIdToSound[surfaceSound.materialId] = sample |
534 | self.soundInformation.surfaceNameToSound[surfaceSound.name] = sample |
535 | end |
536 | end |
537 | |
538 | self.soundInformation.samples.swim = g_soundManager:loadSampleFromXML(xmlFile, "player.sounds.water", "swim", self.baseDirectory, self.rootNode, 0, AudioGroup.ENVIRONMENT, nil, nil) |
539 | self.soundInformation.samples.swimIdle = g_soundManager:loadSampleFromXML(xmlFile, "player.sounds.water", "swimIdle", self.baseDirectory, self.rootNode, 0, AudioGroup.ENVIRONMENT, nil, nil) |
540 | self.soundInformation.samples.plunge = g_soundManager:loadSampleFromXML(xmlFile, "player.sounds.water", "plunge", self.baseDirectory, self.rootNode, 1, AudioGroup.ENVIRONMENT, nil, nil) |
541 | self.soundInformation.samples.flashlight = g_soundManager:loadSampleFromXML(xmlFile, "player.sounds.tools", "flashlight", self.baseDirectory, self.rootNode, 1, AudioGroup.ENVIRONMENT, nil, nil) |
542 | self.soundInformation.samples.horseBrush = g_soundManager:loadSampleFromXML(xmlFile, "player.sounds.tools", "horseBrush", self.baseDirectory, self.rootNode, 0, AudioGroup.ENVIRONMENT, nil, nil) |
543 | else |
544 | for _, surfaceSound in pairs(g_currentMission.surfaceSounds) do |
545 | if surfaceSound.type == "footstep" and surfaceSound.sample ~= nil then |
546 | local sample = g_soundManager:cloneSample2D(surfaceSound.sample, self) |
547 | sample.sampleName = surfaceSound.name |
548 | |
549 | table.insert(self.soundInformation.surfaceSounds, sample) |
550 | self.soundInformation.surfaceIdToSound[surfaceSound.materialId] = sample |
551 | self.soundInformation.surfaceNameToSound[surfaceSound.name] = sample |
552 | end |
553 | end |
554 | |
555 | self.soundInformation.samples.swim = g_soundManager:loadSample2DFromXML(xmlFile, "player.sounds.water", "swim", self.baseDirectory, 0, AudioGroup.ENVIRONMENT) |
556 | self.soundInformation.samples.swimIdle = g_soundManager:loadSample2DFromXML(xmlFile, "player.sounds.water", "swimIdle", self.baseDirectory, 0, AudioGroup.ENVIRONMENT) |
557 | self.soundInformation.samples.plunge = g_soundManager:loadSample2DFromXML(xmlFile, "player.sounds.water", "plunge", self.baseDirectory, 1, AudioGroup.ENVIRONMENT) |
558 | self.soundInformation.samples.flashlight = g_soundManager:loadSample2DFromXML(xmlFile, "player.sounds.tools", "flashlight", self.baseDirectory, 1, AudioGroup.ENVIRONMENT) |
559 | self.soundInformation.samples.horseBrush = g_soundManager:loadSample2DFromXML(xmlFile, "player.sounds.tools", "horseBrush", self.baseDirectory, 0, AudioGroup.ENVIRONMENT) |
560 | end |
561 | |
562 | self.soundInformation.distancePerFootstep.crouch = Utils.getNoNil(getXMLFloat(xmlFile, "player.sounds.footsteps#distancePerFootstepCrouch"), 0.5) |
563 | self.soundInformation.distancePerFootstep.walk = Utils.getNoNil(getXMLFloat(xmlFile, "player.sounds.footsteps#distancePerFootstepWalk"), 0.75) |
564 | self.soundInformation.distancePerFootstep.run = Utils.getNoNil(getXMLFloat(xmlFile, "player.sounds.footsteps#distancePerFootstepRun"), 1.5) |
565 | end |
566 | IKUtil.updateAlignNodes(ikChains, getParentFunc, getParentFuncTarget, parentObj) |
567 | |
568 | delete(xmlFile) |
569 | delete(rootNode) |
570 | return true |
571 | end |
lockInput
DescriptionLocks player inputDefinition
lockInput(bool locked)Arguments
bool | locked | if true, will lock input |
1571 | function Player:lockInput(locked) |
1572 | self.lockedInput = locked |
1573 | 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 |
1047 | function Player:mouseEvent(posX, posY, isDown, isUp, button) |
1048 | end |
movePlayer
DescriptionDefinitionmovePlayer()Code
2491 | function Player:movePlayer(dt, movementX, movementY, movementZ) |
2492 | self.debugFlightCoolDown = self.debugFlightCoolDown - 1 |
2493 | if self.debugFlightMode then |
2494 | movementY = self.inputInformation.moveUp * dt |
2495 | end |
2496 | |
2497 | self.networkInformation.tickTranslation[1] = self.networkInformation.tickTranslation[1] + movementX |
2498 | self.networkInformation.tickTranslation[2] = self.networkInformation.tickTranslation[2] + movementY |
2499 | self.networkInformation.tickTranslation[3] = self.networkInformation.tickTranslation[3] + movementZ |
2500 | moveCCT(self.controllerIndex, movementX, movementY, movementZ, Player.movementCollisionMask) |
2501 | |
2502 | self.networkInformation.index = self.networkInformation.index + 1 |
2503 | if not self.isServer then |
2504 | -- remove old history (above 100 entries) |
2505 | while table.getn(self.networkInformation.history) > 100 do |
2506 | table.remove(self.networkInformation.history, 1) |
2507 | end |
2508 | table.insert(self.networkInformation.history, {index=self.networkInformation.index, movementX=movementX, movementY=movementY, movementZ=movementZ}) |
2509 | end |
2510 | 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 |
1611 | function Player:moveRootNodeToAbsolute(x, y, z) |
1612 | self:moveTo(x, y, z, true, true) |
1613 | 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)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 |
1581 | function Player:moveTo(x, y, z, isAbsolute, isRootNode) |
1582 | self:unequipHandtool() |
1583 | |
1584 | if not self.isServer and self.isOwner then |
1585 | g_client:getServerConnection():sendEvent(PlayerTeleportEvent:new(x, y, z, isAbsolute, isRootNode)) |
1586 | end |
1587 | if not isAbsolute then |
1588 | local terrainHeight = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, 300, z) |
1589 | y = terrainHeight + y |
1590 | end |
1591 | if not isRootNode then |
1592 | y = y + self.baseInformation.capsuleTotalHeight * 0.5 |
1593 | end |
1594 | self:moveToAbsoluteInternal(x, y, z) |
1595 | 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 |
1602 | function Player:moveToAbsolute(x, y, z) |
1603 | self:moveTo(x, y, z, true, false) |
1604 | 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 |
1653 | function Player:moveToAbsoluteInternal(x, y, z) |
1654 | setTranslation(self.rootNode, x, y, z) |
1655 | setTranslation(self.graphicsRootNode, x, y - self.baseInformation.capsuleTotalHeight * 0.5, z) |
1656 | |
1657 | self.networkInformation.interpolationTime:reset() |
1658 | self.networkInformation.interpolatorPosition:setPosition(x,y,z) |
1659 | self.networkInformation.updateTargetTranslationPhysicsIndex = -1 |
1660 | |
1661 | self.lastAnimPosX = x |
1662 | self.lastAnimPosY = y |
1663 | self.lastAnimPosZ = z |
1664 | self.walkDistance = 0 |
1665 | |
1666 | self.baseInformation.lastPositionX, _, self.baseInformation.lastPositionZ = getTranslation(self.graphicsRootNode) |
1667 | 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 |
1618 | function Player:moveToExitPoint(exitVehicle) |
1619 | local exitPoint |
1620 | if exitVehicle.getExitNode ~= nil then |
1621 | exitPoint = exitVehicle:getExitNode() |
1622 | end |
1623 | local x, y, z = getWorldTranslation(exitPoint) |
1624 | local terrainHeight = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, 300, z) |
1625 | y = math.max(terrainHeight + 0.1, y + 0.9) |
1626 | self:moveToAbsolute(x, y, z) |
1627 | local dx, _, dz = localDirectionToWorld(exitPoint, 0, 0, -1) |
1628 | self.rotY = MathUtil.getYRotationFromDirection(dx, dz) |
1629 | |
1630 | --self.targetGraphicsRotY = self.rotY |
1631 | --self.graphicsRotY = self.rotY |
1632 | --(I) setRotation(self.graphicsRootNode, 0, self.graphicsRotY, 0) |
1633 | setRotation(self.cameraNode, self.rotX, self.rotY, 0) |
1634 | 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 |
70 | function Player:new(isServer, isClient) |
71 | local self = Object:new(isServer, isClient, Player_mt) |
72 | |
73 | self.isControlled = false |
74 | self.isOwner = false |
75 | self.isEntered = false |
76 | self.debugFlightModeWalkingSpeed = 0.016 |
77 | self.debugFlightModeRunningFactor = 1 |
78 | |
79 | self.networkInformation = {} |
80 | self.networkInformation.creatorConnection = nil |
81 | self.networkInformation.history = {} |
82 | self.networkInformation.index = 0 |
83 | if self.isServer then |
84 | self.networkInformation.sendIndex = 0 |
85 | end |
86 | self.networkInformation.interpolationTime = InterpolationTime:new(1.2) |
87 | self.networkInformation.interpolatorPosition = InterpolatorPosition:new(0.0, 0.0, 0.0) |
88 | self.networkInformation.interpolatorQuaternion = InterpolatorQuaternion:new(0.0, 0.0, 0.0, 1.0) -- only used on server side for rotation of camera |
89 | self.networkInformation.interpolatorOnGround = InterpolatorValue:new(0.0) |
90 | self.networkInformation.tickTranslation = {0.0, 0.0, 0.0} |
91 | self.networkInformation.dirtyFlag = self:getNextDirtyFlag() |
92 | self.networkInformation.updateTargetTranslationPhysicsIndex = -1 |
93 | self.networkInformation.rotateObject = false |
94 | self.networkInformation.rotateObjectInputV = 0.0 |
95 | self.networkInformation.rotateObjectInputH = 0.0 |
96 | |
97 | self.motionInformation = {} |
98 | self.motionInformation.damping = 0.8 |
99 | self.motionInformation.mass = 80.0 -- in kg |
100 | self.motionInformation.maxAcceleration = 50.0 -- m/s^2 |
101 | self.motionInformation.maxDeceleration = 50.0 -- m/s^2 |
102 | self.motionInformation.inverseMass = 1.0 / self.motionInformation.mass -- in kg ^ -1 |
103 | self.motionInformation.gravity = -9.8 |
104 | self.motionInformation.maxIdleSpeed = 0.1 -- in m/s |
105 | self.motionInformation.maxWalkingSpeed = 4.0 -- in m/s |
106 | self.motionInformation.maxRunningSpeed = 9.0 -- in m/s |
107 | self.motionInformation.maxSwimmingSpeed = 3.0 -- in m/s |
108 | self.motionInformation.maxCrouchingSpeed = 2.0 -- in m/s |
109 | self.motionInformation.maxFallingSpeed = 6.0 -- in m/s |
110 | self.motionInformation.maxCheatRunningSpeed = 34.0 -- in m/s |
111 | self.motionInformation.maxPresentationRunningSpeed = 128.0 -- in m/s |
112 | self.motionInformation.maxSpeedDelay = 0.1 -- in s (how long before max speed is reached) |
113 | self.motionInformation.brakeDelay = 0.001 -- in s (how long before velocity is null) |
114 | self.motionInformation.brakeForce = {0.0, 0.0, 0.0} -- in N (force to apply to stop the player gradually) |
115 | self.motionInformation.currentGroundSpeed = 0.0 -- in m/s |
116 | self.motionInformation.minimumFallingSpeed = -0.00001 -- in m/s |
117 | self.motionInformation.coveredGroundDistance = 0.0 -- in m |
118 | self.motionInformation.currentCoveredGroundDistance = 0.0 |
119 | self.motionInformation.justMoved = false -- |
120 | self.motionInformation.isBraking = false |
121 | self.motionInformation.lastSpeed = 0.0 |
122 | self.motionInformation.currentSpeed = 0.0 |
123 | self.motionInformation.currentSpeedY = 0.0 |
124 | self.motionInformation.isReverse = false |
125 | self.motionInformation.desiredSpeed = 0.0 |
126 | self.motionInformation.jumpHeight = 1.5 -- in m |
127 | self.motionInformation.currentWorldDirX = 0.0 |
128 | self.motionInformation.currentWorldDirZ = 1.0 |
129 | self.motionInformation.currentSpeedX = 0.0 |
130 | self.motionInformation.currentSpeedZ = 0.0 |
131 | |
132 | self.baseInformation = {} |
133 | self.baseInformation.lastPositionX = 0.0 |
134 | self.baseInformation.lastPositionZ = 0.0 |
135 | self.baseInformation.isOnGround = true |
136 | self.baseInformation.isOnGroundPhysics = true |
137 | self.baseInformation.isCloseToGround = true |
138 | self.baseInformation.isInWater = false |
139 | self.baseInformation.wasInWater = false |
140 | self.baseInformation.waterLevel = -1.4 |
141 | self.baseInformation.waterCameraOffset = 0.3 |
142 | self.baseInformation.currentWaterCameraOffset = 0.0 |
143 | self.baseInformation.plungedInWater = false |
144 | self.baseInformation.plungedYVelocityThreshold = -2.0 |
145 | self.baseInformation.isInDebug = false |
146 | self.baseInformation.capsuleHeight = 0.0 |
147 | self.baseInformation.capsuleRadius = 0.0 |
148 | self.baseInformation.tagOffset = {0.0, 1.9, 0.0} |
149 | self.baseInformation.translationAlphaDifference = 0.0 |
150 | self.baseInformation.animDt = 0.0 |
151 | self.baseInformation.isCrouched = false |
152 | self.baseInformation.isUsingChainsawHorizontal = false |
153 | self.baseInformation.isUsingChainsawVertical = false |
154 | self.baseInformation.currentHandtool = nil |
155 | self.baseInformation.capsuleTotalHeight = 0.0 |
156 | self.baseInformation.headBobTime = 0.0 |
157 | self.baseInformation.lastCameraAmplitudeScale = 0.0 |
158 | self.lastEstimatedForwardVelocity = 0.0 |
159 | |
160 | self.inputInformation = {} |
161 | self.inputInformation.moveForward = 0.0 |
162 | self.inputInformation.moveRight = 0.0 |
163 | self.inputInformation.moveUp = 0.0 -- for debug flight mode |
164 | self.inputInformation.pitchCamera = 0.0 |
165 | self.inputInformation.yawCamera = 0.0 |
166 | self.inputInformation.runAxis = 0.0 |
167 | self.inputInformation.crouchState = Player.BUTTONSTATES.RELEASED |
168 | self.inputInformation.interactState = Player.BUTTONSTATES.RELEASED |
169 | |
170 | -- These are the parameters for the input registration and the eventId |
171 | self.inputInformation.registrationList = {} |
172 | 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 } |
173 | 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 } |
174 | 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 } |
175 | 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 } |
176 | 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 } |
177 | 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 } |
178 | -- TODO: read from game settings? also needs to be applied to PlayerStateCrouch.toggleMode. triggerAlways = not crouchToggleMode |
179 | 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 } |
180 | self.inputInformation.registrationList[InputAction.ACTIVATE_OBJECT] = { eventId="", callback=self.onInputActivateObject, triggerUp=false, triggerDown=true, triggerAlways=false, activeType=Player.INPUT_ACTIVE_TYPE.IS_MOVEMENT, callbackState=nil, text="", textVisibility=true } |
181 | 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 } |
182 | 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 } |
183 | 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 } |
184 | 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 } |
185 | 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 } |
186 | 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 } |
187 | self.inputInformation.registrationList[InputAction.NEXT_HANDTOOL] = { eventId="", callback=self.onInputCycleHandTool, triggerUp=false, triggerDown=true, triggerAlways=false, activeType=Player.INPUT_ACTIVE_TYPE.STARTS_DISABLED, callbackState=1, text=g_i18n:getText("input_NEXT_HANDTOOL"), textVisibility=false } |
188 | self.inputInformation.registrationList[InputAction.PREVIOUS_HANDTOOL] = { eventId="", callback=self.onInputCycleHandTool, triggerUp=false, triggerDown=true, triggerAlways=false, activeType=Player.INPUT_ACTIVE_TYPE.STARTS_DISABLED, callbackState=-1, text=g_i18n:getText("input_PREVIOUS_HANDTOOL"), textVisibility=false } |
189 | 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 } |
190 | 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 } |
191 | 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 } |
192 | |
193 | self.soundInformation = {} |
194 | self.soundInformation.samples = {} |
195 | |
196 | self.soundInformation.samples.swim = {} |
197 | self.soundInformation.samples.plunge = {} |
198 | self.soundInformation.samples.horseBrush = {} |
199 | self.soundInformation.samples.handtoolStop = {} |
200 | self.soundInformation.deleteHandtoolStopSampleAfterPlay = false |
201 | self.soundInformation.distancePerFootstep = {} |
202 | self.soundInformation.distancePerFootstep.crouch = 0.5 |
203 | self.soundInformation.distancePerFootstep.walk = 0.75 |
204 | self.soundInformation.distancePerFootstep.run = 1.5 |
205 | self.soundInformation.distanceSinceLastFootstep = 0.0 |
206 | |
207 | self.particleSystemsInformation = {} |
208 | self.particleSystemsInformation.systems = {} |
209 | self.particleSystemsInformation.systems.swim = {} |
210 | self.particleSystemsInformation.systems.plunge = {} |
211 | self.particleSystemsInformation.swimNode = 0 |
212 | self.particleSystemsInformation.plungeNode = 0 |
213 | |
214 | self.animationInformation = {} |
215 | self.animationInformation.player = 0 |
216 | self.animationInformation.parameters = {} |
217 | self.animationInformation.parameters.forwardVelocity = {id=1, value=0.0, type=1} |
218 | self.animationInformation.parameters.verticalVelocity = {id=2, value=0.0, type=1} |
219 | self.animationInformation.parameters.yawVelocity = {id=3, value=0.0, type=1} |
220 | self.animationInformation.parameters.absYawVelocity = {id=4, value=0.0, type=1} |
221 | self.animationInformation.parameters.onGround = {id=5, value=false, type=0} |
222 | self.animationInformation.parameters.inWater = {id=6, value=false, type=0} |
223 | self.animationInformation.parameters.isCrouched = {id=7, value=false, type=0} |
224 | self.animationInformation.parameters.absForwardVelocity = {id=8, value=0.0, type=1} |
225 | self.animationInformation.parameters.isCloseToGround = {id=9, value=false, type=0} |
226 | self.animationInformation.parameters.isUsingChainsawHorizontal = {id=10, value=false, type=0} |
227 | self.animationInformation.parameters.isUsingChainsawVertical = {id=11, value=false, type=0} |
228 | |
229 | -- @see Player.loadCustomization for the content of this struct |
230 | self.visualInformation = nil |
231 | |
232 | -- cached info |
233 | self.animationInformation.oldYaw = 0.0 -- in rad |
234 | self.animationInformation.newYaw = 0.0 -- in rad |
235 | self.animationInformation.estimatedYawVelocity = 0.0 -- in rad/s |
236 | |
237 | -- Player movement lock flag |
238 | self.walkingIsLocked = false |
239 | |
240 | self.canRideAnimal = false |
241 | self.canEnterVehicle = false |
242 | |
243 | self.isLightActive = false |
244 | |
245 | self.rotX = 0 |
246 | self.rotY = 0 |
247 | self.cameraRotY = 0 |
248 | |
249 | self.graphicsRotY = 0 |
250 | self.targetGraphicsRotY = 0 |
251 | |
252 | self.camera = 0 |
253 | |
254 | self.time = 0 |
255 | |
256 | self.lightNode = nil |
257 | |
258 | self.clipDistance = 500 |
259 | |
260 | self.lastAnimPosX = 0 |
261 | self.lastAnimPosY = 0 |
262 | self.lastAnimPosZ = 0 |
263 | |
264 | self.walkDistance = 0 |
265 | self.animUpdateTime = 0 |
266 | |
267 | self.debugFlightMode = false |
268 | self.debugFlightCoolDown = 0 |
269 | |
270 | self.requestedFieldData = false |
271 | |
272 | self.playerStateMachine = PlayerStateMachine:new(self) |
273 | |
274 | self.farmId = FarmManager.SPECTATOR_FARM_ID |
275 | |
276 | return self |
277 | 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 |
1720 | function Player:onEnter(isControlling) |
1721 | self:raiseActive() |
1722 | if self.foliageBendingNode ~= nil and self.foliageBendingId == nil then |
1723 | -- foliage bending |
1724 | self.foliageBendingId = g_currentMission.foliageBendingSystem:createRectangle(-0.5, 0.5, -0.5, 0.5, 0.4, self.foliageBendingNode) |
1725 | end |
1726 | |
1727 | if self.isServer then |
1728 | self:setOwner(self.networkInformation.creatorConnection) |
1729 | end |
1730 | if isControlling or self.isServer then |
1731 | self:raiseDirtyFlags(self.networkInformation.dirtyFlag) |
1732 | end |
1733 | |
1734 | self.isControlled = true |
1735 | if isControlling then |
1736 | g_messageCenter:subscribe(MessageType.INPUT_BINDINGS_CHANGED, self.onInputBindingsChanged, self) |
1737 | g_currentMission:addPauseListeners(self, Player.onPausGame) |
1738 | setRotation(self.cameraNode, 0, 0, 0) |
1739 | setCamera(self.cameraNode) |
1740 | self.isEntered = true |
1741 | self:setVisibility(false) |
1742 | self:registerActionEvents() |
1743 | else |
1744 | self:setVisibility(true) |
1745 | end |
1746 | if self.isServer and not self.isEntered and g_currentMission.trafficSystem ~= nil and g_currentMission.trafficSystem.trafficSystemId ~= 0 then |
1747 | addTrafficSystemPlayer(g_currentMission.trafficSystem.trafficSystemId, self.graphicsRootNode) |
1748 | end |
1749 | self.isLightActive = false |
1750 | end |
onEnterFarmhouse
DescriptionDefinitiononEnterFarmhouse()Code
2298 | function Player:onEnterFarmhouse() |
2299 | if self.isServer then |
2300 | local dogHouse = g_currentMission:getDoghouse(self.farmId) |
2301 | if dogHouse ~= nil and dogHouse.dog ~= nil and dogHouse.dog.entityFollow == self.rootNode then |
2302 | dogHouse.dog:teleportToSpawn() |
2303 | end |
2304 | end |
2305 | end |
onGhostAdd
DescriptionEmpty functionDefinition
onGhostAdd()Code
1866 | function Player:onGhostAdd() |
1867 | end |
onGhostRemove
DescriptionDeletes playerDefinition
onGhostRemove()Code
1860 | function Player:onGhostRemove() |
1861 | self:delete() |
1862 | end |
onInputActivateHandtool
DescriptionDefinitiononInputActivateHandtool()Code
3129 | function Player:onInputActivateHandtool(_, inputValue) |
3130 | if self:hasHandtoolEquipped() then |
3131 | self.baseInformation.currentHandtool.activatePressed = inputValue ~= 0 |
3132 | end |
3133 | end |
onInputActivateObject
DescriptionEvent function for interacting with an animalDefinition
onInputActivateObject()Code
3047 | function Player:onInputActivateObject(_, inputValue) |
3048 | if self.playerStateMachine:isAvailable("activateObject") then |
3049 | self.playerStateMachine:activateState("activateObject") |
3050 | elseif self.playerStateMachine:isAvailable("animalFeed") then |
3051 | self.playerStateMachine:activateState("animalFeed") |
3052 | elseif self.playerStateMachine:isAvailable("animalPet") then |
3053 | self.playerStateMachine:activateState("animalPet") |
3054 | end |
3055 | end |
onInputCrouch
DescriptionEvent function for crouching.Definition
onInputCrouch()Code
2965 | function Player:onInputCrouch(_, inputValue) |
2966 | if self.playerStateMachine:isAvailable("crouch") then |
2967 | self.playerStateMachine:activateState("crouch") |
2968 | end |
2969 | |
2970 | self.inputInformation.crouchState = Player.BUTTONSTATES.PRESSED |
2971 | 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 |
3070 | function Player:onInputCycleHandTool(_, _, direction) |
3071 | if self.playerStateMachine:isAvailable("cycleHandtool") then |
3072 | local cycleHandtoolState = self.playerStateMachine:getState("cycleHandtool") |
3073 | cycleHandtoolState.cycleDirection = direction |
3074 | self.playerStateMachine:activateState("cycleHandtool") |
3075 | end |
3076 | end |
onInputDebugFlyToggle
DescriptionEvent function for the debug flying toggle.Definition
onInputDebugFlyToggle()Code
3088 | function Player:onInputDebugFlyToggle() |
3089 | if not self.walkingIsDisabled then |
3090 | if self.debugFlightCoolDown <= 0 then |
3091 | if g_flightAndNoHUDKeysEnabled then |
3092 | self.debugFlightMode = not self.debugFlightMode |
3093 | self.debugFlightCoolDown = 10 |
3094 | end |
3095 | end |
3096 | end |
3097 | end |
onInputDebugFlyUpDown
DescriptionEvent function for the debug flying vertical movement.Definition
onInputDebugFlyUpDown(nil, float inputValue)Arguments
nil | ||
float | inputValue |
3103 | function Player:onInputDebugFlyUpDown(_, inputValue) |
3104 | if not self.walkingIsDisabled then |
3105 | local move = inputValue * 0.5 * self.debugFlightModeWalkingSpeed * self.debugFlightModeRunningFactor |
3106 | self.inputInformation.moveUp = self.inputInformation.moveUp + move |
3107 | end |
3108 | end |
onInputEnter
DescriptionEvent function for enterDefinition
onInputEnter(nil, float inputValue)Arguments
nil | ||
float | inputValue |
3114 | function Player:onInputEnter(_, inputValue) |
3115 | if g_time > g_currentMission.lastInteractionTime + 200 then |
3116 | local enterVehicle = false |
3117 | if g_currentMission.interactiveVehicleInRange and g_currentMission.accessHandler:canFarmAccess(self.farmId, g_currentMission.interactiveVehicleInRange) then |
3118 | g_currentMission.interactiveVehicleInRange:interact() |
3119 | enterVehicle = true |
3120 | elseif self.canRideAnimal then |
3121 | self.playerStateMachine:activateState("animalRide") |
3122 | enterVehicle = true |
3123 | end |
3124 | end |
3125 | end |
onInputInteract
DescriptionEvent function for interacting with an animalDefinition
onInputInteract()Code
3027 | function Player:onInputInteract(_, inputValue) |
3028 | -- Note: we need to store pressed state for animal cleaning (see PlayerStateAnimalInteract) which is a continuous |
3029 | -- action. Therefore, this event is called onUp and onDown. When the down event is received, input will be non-zero. |
3030 | if self.inputInformation.interactState ~= Player.BUTTONSTATES.PRESSED and inputValue ~= 0 then |
3031 | if self.playerStateMachine:isAvailable("drop") then |
3032 | self.playerStateMachine:activateState("drop") |
3033 | elseif self.playerStateMachine:isAvailable("pickup") then |
3034 | self.playerStateMachine:activateState("pickup") |
3035 | elseif self.playerStateMachine:isAvailable("animalInteract") then |
3036 | self.playerStateMachine:activateState("animalInteract") |
3037 | end |
3038 | |
3039 | self.inputInformation.interactState = Player.BUTTONSTATES.PRESSED |
3040 | else |
3041 | self.inputInformation.interactState = Player.BUTTONSTATES.RELEASED |
3042 | end |
3043 | end |
onInputJump
DescriptionEvent function for jumping.Definition
onInputJump()Code
3019 | function Player:onInputJump(_, inputValue) |
3020 | if self.playerStateMachine:isAvailable("jump") then |
3021 | self.playerStateMachine:activateState("jump") |
3022 | end |
3023 | end |
onInputLookLeftRight
DescriptionEvent function for player camera horizontal axis.Definition
onInputLookLeftRight(nil, float inputValue)Arguments
nil | ||
float | inputValue |
2899 | function Player:onInputLookLeftRight(_, inputValue, _, _, isMouse) |
2900 | if not self.lockedInput then |
2901 | if isMouse then |
2902 | inputValue = inputValue * 0.001 * 16.666 |
2903 | else |
2904 | inputValue = inputValue * g_currentDt *0.001 |
2905 | end |
2906 | self.inputInformation.yawCamera = self.inputInformation.yawCamera + inputValue |
2907 | end |
2908 | self.inputInformation.isMouseRotation = isMouse |
2909 | end |
onInputLookUpDown
DescriptionEvent function for player camera vertical axis.Definition
onInputLookUpDown(nil, float inputValue)Arguments
nil | ||
float | inputValue |
2915 | function Player:onInputLookUpDown(_, inputValue, _, _, isMouse) |
2916 | if not self.lockedInput then |
2917 | local pitchValue = g_gameSettings:getValue("invertYLook") and -inputValue or inputValue |
2918 | if isMouse then |
2919 | pitchValue = pitchValue * 0.001 * 16.666 |
2920 | else |
2921 | pitchValue = pitchValue * g_currentDt *0.001 |
2922 | end |
2923 | self.inputInformation.pitchCamera = self.inputInformation.pitchCamera + pitchValue |
2924 | end |
2925 | end |
onInputMoveForward
DescriptionEvent function for player forward/backward movement.Definition
onInputMoveForward(nil, float inputValue)Arguments
nil | ||
float | inputValue |
2941 | function Player:onInputMoveForward(_, inputValue) |
2942 | if not self.lockedInput then |
2943 | self.inputInformation.moveForward = self.inputInformation.moveForward + inputValue |
2944 | end |
2945 | end |
onInputMoveSide
DescriptionEvent function for player strafe movement.Definition
onInputMoveSide(nil, float inputValue)Arguments
nil | ||
float | inputValue |
2931 | function Player:onInputMoveSide(_, inputValue) |
2932 | if not self.lockedInput then |
2933 | self.inputInformation.moveRight = self.inputInformation.moveRight + inputValue |
2934 | end |
2935 | end |
onInputRotateObjectHorizontally
DescriptionEvent function for rotating object.Definition
onInputRotateObjectHorizontally()Code
2975 | function Player:onInputRotateObjectHorizontally(_, inputValue) |
2976 | if self.pickedUpObjectJointId ~= nil and math.abs(inputValue) > 0 then |
2977 | self:rotateObject(inputValue, 0.0, 1.0, 0.0) |
2978 | elseif self.isCarryingObject and self.isClient and self.isControlled then |
2979 | if inputValue ~= 0.0 then |
2980 | self.networkInformation.rotateObject = true |
2981 | else |
2982 | self.networkInformation.rotateObject = false |
2983 | end |
2984 | self.networkInformation.rotateObjectInputH = inputValue |
2985 | end |
2986 | end |
onInputRotateObjectVertically
DescriptionEvent function for rotating object.Definition
onInputRotateObjectVertically()Code
2990 | function Player:onInputRotateObjectVertically(_, inputValue) |
2991 | if self.pickedUpObjectJointId ~= nil and math.abs(inputValue) > 0 then |
2992 | self:rotateObject(inputValue, 1.0, 0.0, 0.0) |
2993 | elseif self.isCarryingObject and self.isClient and self.isControlled then |
2994 | if inputValue ~= 0.0 then |
2995 | self.networkInformation.rotateObject = true |
2996 | else |
2997 | self.networkInformation.rotateObject = false |
2998 | end |
2999 | self.networkInformation.rotateObjectInputV = inputValue |
3000 | end |
3001 | end |
onInputRun
DescriptionEvent function for player running.Definition
onInputRun(nil, float inputValue)Arguments
nil | ||
float | inputValue |
2951 | function Player:onInputRun(_, inputValue) |
2952 | self.inputInformation.runAxis = inputValue |
2953 | |
2954 | if self.debugFlightMode then |
2955 | if inputValue > 0 and self.debugFlightModeRunningFactor ~= 4.0 then |
2956 | self.debugFlightModeRunningFactor = 4.0 |
2957 | elseif inputValue == 0 and self.debugFlightModeRunningFactor ~= 1.0 then |
2958 | self.debugFlightModeRunningFactor = 1.0 |
2959 | end |
2960 | end |
2961 | end |
onInputThrowObject
DescriptionEvent function for throwing an object.Definition
onInputThrowObject()Code
3080 | function Player:onInputThrowObject(_, inputValue) |
3081 | if self.playerStateMachine:isAvailable("throw") then |
3082 | self.playerStateMachine:activateState("throw") |
3083 | end |
3084 | end |
onInputToggleLight
DescriptionEvent function for flashlight toggle.Definition
onInputToggleLight()Code
3059 | function Player:onInputToggleLight() |
3060 | if self.playerStateMachine:isAvailable("useLight") then |
3061 | self.playerStateMachine:activateState("useLight") |
3062 | end |
3063 | 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
1761 | function Player:onLeave() |
1762 | if self.isControlled then |
1763 | g_messageCenter:unsubscribe(MessageType.INPUT_BINDINGS_CHANGED, self) |
1764 | end |
1765 | |
1766 | -- stop swim sound |
1767 | if g_soundManager:getIsSamplePlaying(self.soundInformation.samples.swim) then |
1768 | g_soundManager:stopSample(self.soundInformation.samples.swim) |
1769 | end |
1770 | if g_soundManager:getIsSamplePlaying(self.soundInformation.samples.swimIdle) then |
1771 | g_soundManager:stopSample(self.soundInformation.samples.swimIdle) |
1772 | end |
1773 | |
1774 | self:removeActionEvents() |
1775 | -- unregister animal interess |
1776 | for husbandryId, _ in pairs(g_currentMission.husbandries) do |
1777 | setAnimalInteressNode(husbandryId, 0) |
1778 | end |
1779 | |
1780 | if self.foliageBendingId ~= nil then |
1781 | g_currentMission.foliageBendingSystem:destroyObject(self.foliageBendingId) |
1782 | self.foliageBendingId = nil |
1783 | end |
1784 | |
1785 | if self.isServer then |
1786 | self:setOwner(nil) |
1787 | end |
1788 | if self.isEntered or self.isServer then |
1789 | self:raiseDirtyFlags(self.networkInformation.dirtyFlag) |
1790 | end |
1791 | if self.isServer and not self.isEntered and g_currentMission.trafficSystem ~= nil and g_currentMission.trafficSystem.trafficSystemId ~= 0 then |
1792 | removeTrafficSystemPlayer(g_currentMission.trafficSystem.trafficSystemId, self.graphicsRootNode) |
1793 | end |
1794 | |
1795 | g_currentMission:addPauseListeners(self) |
1796 | |
1797 | --clear history |
1798 | self.networkInformation.history = {} |
1799 | self.isControlled = false |
1800 | self.isEntered = false |
1801 | self:setVisibility(false) |
1802 | |
1803 | if self:hasHandtoolEquipped() then |
1804 | self.baseInformation.currentHandtool:onDeactivate() |
1805 | self.baseInformation.currentHandtool:delete() |
1806 | self.baseInformation.currentHandtool = nil |
1807 | end |
1808 | local dogHouse = g_currentMission:getDoghouse(self.farmId) |
1809 | if dogHouse ~= nil and dogHouse.dog ~= nil then |
1810 | dogHouse.dog:onPlayerLeave(self) |
1811 | end |
1812 | |
1813 | if self.lightNode ~= nil then |
1814 | setVisibility(self.lightNode, false) |
1815 | end |
1816 | self:moveToAbsoluteInternal(0, -200, 0) |
1817 | end |
onLeaveVehicle
DescriptionCalled when player leaves vehicleDefinition
onLeaveVehicle()Code
1754 | function Player:onLeaveVehicle() |
1755 | self.playerStateMachine:deactivateState("animalRide") |
1756 | self.playerStateMachine:deactivateState("jump") |
1757 | 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 |
2350 | function Player:onPickedUpObjectJointBreak(jointIndex, breakingImpulse) |
2351 | if jointIndex == self.pickedUpObjectJointId then |
2352 | self:pickUpObject(false) |
2353 | end |
2354 | -- Do not delete the joint internally, we already deleted it |
2355 | return false |
2356 | 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 |
2043 | function Player:pickUpObject(state, noEventSend) |
2044 | PlayerPickUpObjectEvent.sendEvent(self, state, noEventSend) |
2045 | if self.isServer then |
2046 | if state and (self.isObjectInRange and self.lastFoundObject ~= nil) and not self.isCarryingObject then |
2047 | local constr = JointConstructor:new() |
2048 | |
2049 | -- disable collision with CCT |
2050 | self.pickedUpObjectCollisionMask = getCollisionMask(self.lastFoundObject) |
2051 | local newPickedUpObjectCollisionFlag = bitXOR(bitAND(self.pickedUpObjectCollisionMask, Player.movementCollisionMask), self.pickedUpObjectCollisionMask) |
2052 | setCollisionMask(self.lastFoundObject, newPickedUpObjectCollisionFlag) |
2053 | |
2054 | constr:setActors(self.pickUpKinematicHelperNode, self.lastFoundObject) |
2055 | |
2056 | for i=0, 2 do |
2057 | constr:setRotationLimit(i, 0, 0) |
2058 | constr:setTranslationLimit(i, true, 0, 0) |
2059 | end |
2060 | |
2061 | -- set position of joint |
2062 | local mx, my, mz = getCenterOfMass(self.lastFoundObject) |
2063 | local wx, wy, wz = localToWorld(self.lastFoundObject, mx, my, mz) |
2064 | constr:setJointWorldPositions(wx, wy, wz, wx, wy, wz) |
2065 | |
2066 | local nx, ny, nz = localDirectionToWorld(self.lastFoundObject, 1, 0, 0) |
2067 | constr:setJointWorldAxes(nx, ny, nz, nx, ny, nz) |
2068 | |
2069 | local yx, yy, yz = localDirectionToWorld(self.lastFoundObject, 0, 1, 0) |
2070 | constr:setJointWorldNormals(yx, yy, yz, yx, yy, yz) |
2071 | constr:setEnableCollision(false) |
2072 | |
2073 | setWorldTranslation(self.pickUpKinematicHelperNodeChild, wx, wy, wz) |
2074 | setWorldRotation(self.pickUpKinematicHelperNodeChild, getWorldRotation(self.lastFoundObject)) |
2075 | |
2076 | -- set spring/damper ?! |
2077 | local dampingRatio = 1.0 |
2078 | local mass = getMass(self.lastFoundObject) |
2079 | |
2080 | local rotationLimitSpring = {} |
2081 | local rotationLimitDamper = {} |
2082 | for i=1, 3 do |
2083 | rotationLimitSpring[i] = mass * 60 |
2084 | rotationLimitDamper[i] = dampingRatio * 2 * math.sqrt( mass * rotationLimitSpring[i] ) |
2085 | --print(" rotSpring/Damper = "..tostring(rotationLimitSpring[i]).." / "..tostring(rotationLimitDamper[i])) |
2086 | end |
2087 | constr:setRotationLimitSpring(rotationLimitSpring[1], rotationLimitDamper[1], rotationLimitSpring[2], rotationLimitDamper[2], rotationLimitSpring[3], rotationLimitDamper[3]) |
2088 | |
2089 | local translationLimitSpring = {} |
2090 | local translationLimitDamper = {} |
2091 | for i=1, 3 do |
2092 | translationLimitSpring[i] = mass * 60 |
2093 | translationLimitDamper[i] = dampingRatio * 2 * math.sqrt( mass * translationLimitSpring[i] ) |
2094 | --print(" transSpring/Damper = "..tostring(translationLimitSpring[i]).." / "..tostring(translationLimitDamper[i])) |
2095 | end |
2096 | constr:setTranslationLimitSpring(translationLimitSpring[1], translationLimitDamper[1], translationLimitSpring[2], translationLimitDamper[2], translationLimitSpring[3], translationLimitDamper[3]) |
2097 | |
2098 | local forceAcceleration = 4 |
2099 | local forceLimit = forceAcceleration * mass * 40.0 |
2100 | constr:setBreakable(forceLimit, forceLimit) |
2101 | |
2102 | self.pickedUpObjectJointId = constr:finalize() |
2103 | |
2104 | addJointBreakReport(self.pickedUpObjectJointId, "onPickedUpObjectJointBreak", self) |
2105 | |
2106 | self.pickedUpObject = self.lastFoundObject |
2107 | self.isCarryingObject = true |
2108 | Player.PICKED_UP_OBJECTS[self.pickedUpObject] = true |
2109 | |
2110 | local object = g_currentMission:getNodeObject(self.pickedUpObject) |
2111 | if object ~= nil then |
2112 | object.thrownFromPosition = nil |
2113 | end |
2114 | else |
2115 | if self.pickedUpObjectJointId ~= nil then |
2116 | removeJoint(self.pickedUpObjectJointId) |
2117 | self.pickedUpObjectJointId = nil |
2118 | self.isCarryingObject = false |
2119 | Player.PICKED_UP_OBJECTS[self.pickedUpObject] = false |
2120 | |
2121 | if entityExists(self.pickedUpObject) then |
2122 | local vx, vy, vz = getLinearVelocity(self.pickedUpObject) |
2123 | vx = MathUtil.clamp(vx, -5, 5) |
2124 | vy = MathUtil.clamp(vy, -5, 5) |
2125 | vz = MathUtil.clamp(vz, -5, 5) |
2126 | setLinearVelocity(self.pickedUpObject, vx, vy, vz) |
2127 | -- setAngularVelocity(self.pickedUpObject, vx, vy, vz) |
2128 | setCollisionMask(self.pickedUpObject, self.pickedUpObjectCollisionMask) |
2129 | self.pickedUpObjectCollisionMask = 0 |
2130 | end |
2131 | |
2132 | local object = g_currentMission:getNodeObject(self.pickedUpObject) |
2133 | if object ~= nil then |
2134 | object.thrownFromPosition = nil |
2135 | end |
2136 | self.pickedUpObject = nil |
2137 | end |
2138 | end |
2139 | end |
2140 | 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 |
2003 | function Player:pickUpObjectRaycastCallback(hitObjectId, x, y, z, distance) |
2004 | if hitObjectId ~= g_currentMission.terrainDetailId and Player.PICKED_UP_OBJECTS[hitObjectId] ~= true then |
2005 | if getRigidBodyType(hitObjectId) == "Dynamic" then |
2006 | |
2007 | local mass = getMass(hitObjectId) |
2008 | -- check if mounted: |
2009 | local canBePickedUp = true |
2010 | local object = g_currentMission:getNodeObject(hitObjectId) |
2011 | if object ~= nil then |
2012 | if object.dynamicMountObject ~= nil then |
2013 | canBePickedUp = false |
2014 | end |
2015 | if object.getTotalMass ~= nil then |
2016 | mass = object:getTotalMass() |
2017 | end |
2018 | if object.getCanBePickedUp ~= nil then |
2019 | if not object:getCanBePickedUp(self) then |
2020 | canBePickedUp = false |
2021 | end |
2022 | end |
2023 | end |
2024 | |
2025 | if canBePickedUp then |
2026 | self.lastFoundObject = hitObjectId |
2027 | self.lastFoundObjectMass = mass |
2028 | self.lastFoundObjectHitPoint = {x, y, z} |
2029 | end |
2030 | |
2031 | -- only consider first potentially valid object |
2032 | return false |
2033 | end |
2034 | end |
2035 | |
2036 | return true |
2037 | end |
playHandToolStopSample
DescriptionDefinitionplayHandToolStopSample()Code
2281 | function Player:playHandToolStopSample() |
2282 | if self.soundInformation.samples.handtoolStop.soundSample ~= nil then |
2283 | g_soundManager:playSample(self.soundInformation.samples.handtoolStop) |
2284 | self.soundInformation.deleteHandtoolStopSampleAfterPlay = true |
2285 | end |
2286 | end |
readStream
DescriptionReads from network streamDefinition
readStream(integer streamId, table connection)Arguments
integer | streamId | id of the stream to read |
table | connection | connection information |
765 | function Player:readStream(streamId, connection) |
766 | Player:superClass().readStream(self, streamId) |
767 | local isOwner = streamReadBool(streamId) |
768 | local filename = NetworkUtil.convertFromNetworkFilename(streamReadString(streamId)) |
769 | local x = streamReadFloat32(streamId) |
770 | local y = streamReadFloat32(streamId) |
771 | local z = streamReadFloat32(streamId) |
772 | local isControlled = streamReadBool(streamId) |
773 | if self.visualInformation == nil then |
774 | self.visualInformation = PlayerStyle:new() |
775 | end |
776 | self.visualInformation:readStream(streamId, connection) |
777 | self.farmId = streamReadUIntN(streamId, FarmManager.FARM_ID_SEND_NUM_BITS) |
778 | if self.filename == nil then |
779 | self:load(filename, self.visualInformation, connection, isOwner) |
780 | end |
781 | self:moveToAbsoluteInternal(x, y, z) |
782 | |
783 | self:setLightIsActive(streamReadBool(streamId), true) |
784 | |
785 | if isControlled ~= self.isControlled then |
786 | if isControlled then |
787 | self:onEnter(false) |
788 | else |
789 | self:onLeave() |
790 | end |
791 | end |
792 | |
793 | local hasHandtool = streamReadBool(streamId) |
794 | if hasHandtool then |
795 | local handtoolFilename = NetworkUtil.convertFromNetworkFilename(streamReadString(streamId)) |
796 | self:equipHandtool(handtoolFilename, true, true) |
797 | end |
798 | 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 |
831 | function Player:readUpdateStream(streamId, timestamp, connection) |
832 | if connection:getIsServer() then |
833 | -- client code (read data from server) |
834 | local x = streamReadFloat32(streamId) |
835 | local y = streamReadFloat32(streamId) |
836 | local z = streamReadFloat32(streamId) |
837 | local alpha = streamReadFloat32(streamId) |
838 | self.cameraRotY = alpha |
839 | |
840 | self.isObjectInRange = streamReadBool(streamId) |
841 | if self.isObjectInRange then |
842 | self.lastFoundObjectMass = streamReadFloat32(streamId) |
843 | else |
844 | self.lastFoundObjectMass = nil |
845 | end |
846 | self.isCarryingObject = streamReadBool(streamId) |
847 | local isOnGround = streamReadBool(streamId) |
848 | |
849 | if self.isOwner then |
850 | local index = streamReadInt32(streamId) |
851 | --print("CLIENT ( "..tostring(self).." ): x/y/z = "..tostring(x).." / "..tostring(y).." / "..tostring(z)) |
852 | -- remove history entries before the one sent by the server |
853 | while self.networkInformation.history[1] ~= nil and self.networkInformation.history[1].index <= index do |
854 | table.remove(self.networkInformation.history, 1) |
855 | end |
856 | -- set position sent by server |
857 | setCCTPosition(self.controllerIndex, x, y, z) |
858 | -- move cct from the rest of the history queue |
859 | -- Accumulate moves from multiple history entries so that we never apply more than 5 moveCCT's |
860 | local history = self.networkInformation.history |
861 | local numHistory = #history |
862 | if numHistory <= 5 then |
863 | for i=1,numHistory do |
864 | moveCCT(self.controllerIndex, history[i].movementX, history[i].movementY, history[i].movementZ, Player.movementCollisionMask) |
865 | end |
866 | else |
867 | -- Accumulate moves with different amounts so that we achieve exactly the correct historty |
868 | -- Some will use floored, some will use floored + 1 |
869 | -- Use the smaller amount for the older moves as errors for older moves potentially leads to larger errors now than for more recent ones |
870 | local accumSizeSmall = math.floor(numHistory / 5) |
871 | local numSmall = 5 - numHistory + accumSizeSmall * 5 |
872 | local startI = 1 |
873 | for i=1,5 do |
874 | local endI |
875 | if i <= numSmall then |
876 | endI = startI+accumSizeSmall-1 |
877 | else |
878 | endI = startI+accumSizeSmall |
879 | end |
880 | local movementX, movementY, movementZ = 0,0,0 |
881 | for j=startI,endI do |
882 | movementX = movementX + history[j].movementX |
883 | movementY = movementY + history[j].movementY |
884 | movementZ = movementZ + history[j].movementZ |
885 | end |
886 | moveCCT(self.controllerIndex, movementX, movementY, movementZ, Player.movementCollisionMask) |
887 | startI = endI+1 |
888 | end |
889 | end |
890 | -- set target physics index to current index |
891 | self.networkInformation.updateTargetTranslationPhysicsIndex = getPhysicsUpdateIndex() -- update until the current physics index is simulated |
892 | -- [animation] |
893 | self.baseInformation.isCrouched = streamReadBool(streamId) |
894 | -- |
895 | else |
896 | local isControlled = streamReadBool(streamId) |
897 | if isControlled ~= self.isControlled then |
898 | self:moveToAbsoluteInternal(x, y, z) |
899 | if isControlled then |
900 | self:onEnter(false) |
901 | else |
902 | self:onLeave() |
903 | end |
904 | else |
905 | -- other clients: set position, refrain from using target index and start new network interpolation phase |
906 | setTranslation(self.rootNode, x, y, z) |
907 | self.networkInformation.interpolatorPosition:setTargetPosition(x, y, z) |
908 | if isOnGround then |
909 | self.networkInformation.interpolatorOnGround:setTargetValue(1.0) |
910 | else |
911 | self.networkInformation.interpolatorOnGround:setTargetValue(0.0) |
912 | end |
913 | self.networkInformation.updateTargetTranslationPhysicsIndex = -1 |
914 | self.networkInformation.interpolationTime:startNewPhaseNetwork() |
915 | -- force update |
916 | self:raiseActive() |
917 | end |
918 | -- [animation] |
919 | self.baseInformation.isCrouched = streamReadBool(streamId) |
920 | -- |
921 | end |
922 | else |
923 | -- server code (read data from client) |
924 | if connection == self.networkInformation.creatorConnection then |
925 | -- 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() |
926 | local movementX=streamReadFloat32(streamId) |
927 | local movementY=streamReadFloat32(streamId) |
928 | local movementZ=streamReadFloat32(streamId) |
929 | |
930 | local qx = streamReadFloat32(streamId) |
931 | local qy = streamReadFloat32(streamId) |
932 | local qz = streamReadFloat32(streamId) |
933 | local qw = streamReadFloat32(streamId) |
934 | |
935 | local index = streamReadInt32(streamId) |
936 | local isControlled = streamReadBool(streamId) |
937 | |
938 | moveCCT(self.controllerIndex, movementX, movementY, movementZ, Player.movementCollisionMask) |
939 | |
940 | self.networkInformation.interpolationTime:startNewPhaseNetwork() |
941 | self.networkInformation.interpolatorQuaternion:setTargetQuaternion(qx, qy, qz, qw) |
942 | local physicsIndex = getPhysicsUpdateIndex() |
943 | table.insert(self.networkInformation.history, {index=index, physicsIndex = physicsIndex}) |
944 | |
945 | self.networkInformation.updateTargetTranslationPhysicsIndex = physicsIndex -- update until the current physics index is simulated |
946 | |
947 | self:raiseActive() |
948 | if isControlled ~= self.isControlled then |
949 | if isControlled then |
950 | self:onEnter(false) |
951 | else |
952 | self:onLeave() |
953 | end |
954 | end |
955 | -- [animation] |
956 | self.baseInformation.isCrouched = streamReadBool(streamId) |
957 | -- |
958 | if self.isCarryingObject then |
959 | self.networkInformation.rotateObject = streamReadBool(streamId) |
960 | if self.networkInformation.rotateObject then |
961 | self.networkInformation.rotateObjectInputH = streamReadFloat32(streamId) |
962 | self.networkInformation.rotateObjectInputV = streamReadFloat32(streamId) |
963 | end |
964 | end |
965 | end |
966 | end |
967 | end |
recordPositionInformation
DescriptionDefinitionrecordPositionInformation()Code
2671 | function Player:recordPositionInformation() |
2672 | local currentPositionX, _, currentPositionZ = getTranslation(self.graphicsRootNode) |
2673 | local deltaPosX = currentPositionX - self.baseInformation.lastPositionX |
2674 | local deltaPosZ = currentPositionZ - self.baseInformation.lastPositionZ |
2675 | self.baseInformation.lastPositionX = currentPositionX |
2676 | self.baseInformation.lastPositionZ = currentPositionZ |
2677 | |
2678 | local groundDistanceCovered = MathUtil.vector2Length(deltaPosX, deltaPosZ) |
2679 | self.motionInformation.justMoved = groundDistanceCovered > 0.0 |
2680 | if self.baseInformation.isOnGround then |
2681 | self.motionInformation.currentCoveredGroundDistance = groundDistanceCovered |
2682 | self.motionInformation.coveredGroundDistance = self.motionInformation.coveredGroundDistance + groundDistanceCovered |
2683 | end |
2684 | end |
registerActionEvents
DescriptionRegister required player action events.Definition
registerActionEvents()Code
2848 | function Player:registerActionEvents() |
2849 | -- register action events for the player context without switching (important when this is called from within the UI context) |
2850 | g_inputBinding:beginActionEventsModification(Player.INPUT_CONTEXT_NAME) |
2851 | |
2852 | for actionId, inputRegisterEntry in pairs(self.inputInformation.registrationList) do |
2853 | local eventAdded = false |
2854 | local startActive = false |
2855 | |
2856 | if inputRegisterEntry.activeType == Player.INPUT_ACTIVE_TYPE.STARTS_ENABLED then |
2857 | startActive = true |
2858 | elseif inputRegisterEntry.activeType == Player.INPUT_ACTIVE_TYPE.STARTS_DISABLED then |
2859 | startActive = false |
2860 | elseif inputRegisterEntry.activeType == Player.INPUT_ACTIVE_TYPE.IS_MOVEMENT then |
2861 | startActive = not self.walkingIsLocked |
2862 | elseif inputRegisterEntry.activeType == Player.INPUT_ACTIVE_TYPE.IS_CARRYING then |
2863 | startActive = self.isCarryingObject |
2864 | elseif inputRegisterEntry.activeType == Player.INPUT_ACTIVE_TYPE.IS_DEBUG then |
2865 | startActive = self.baseInformation.isInDebug |
2866 | end |
2867 | |
2868 | -- register with conflict removal flag, will disable conflicting bindings of newly registered actions |
2869 | eventAdded, inputRegisterEntry.eventId = g_inputBinding:registerActionEvent(actionId, self, inputRegisterEntry.callback, inputRegisterEntry.triggerUp, inputRegisterEntry.triggerDown, inputRegisterEntry.triggerAlways, startActive, inputRegisterEntry.callbackState, true) |
2870 | if inputRegisterEntry.text ~= nil and inputRegisterEntry.text ~= "" then |
2871 | g_inputBinding:setActionEventText(inputRegisterEntry.eventId, inputRegisterEntry.text) |
2872 | end |
2873 | |
2874 | g_inputBinding:setActionEventTextVisibility(inputRegisterEntry.eventId, inputRegisterEntry.textVisibility) |
2875 | end |
2876 | -- reset registration context, update event data in input system: |
2877 | g_inputBinding:endActionEventsModification() |
2878 | end |
removeActionEvents
DescriptionRemove all player action events.Definition
removeActionEvents()Code
2882 | function Player:removeActionEvents() |
2883 | -- reset previously disabled bindings' enabled state |
2884 | g_inputBinding:resetActiveActionBindings() |
2885 | |
2886 | -- modify action events in player context without switching (important because this can be called from within the UI) |
2887 | g_inputBinding:beginActionEventsModification(Player.INPUT_CONTEXT_NAME) |
2888 | g_inputBinding:removeActionEventsByTarget(self) |
2889 | for _, inputRegisterEntry in pairs(self.inputInformation.registrationList) do |
2890 | inputRegisterEntry.eventId = "" |
2891 | end |
2892 | g_inputBinding:endActionEventsModification() |
2893 | end |
resetBrake
DescriptionDefinitionresetBrake()Code
2701 | function Player:resetBrake() |
2702 | self:setVelocityToMotion(0.0, 0.0, 0.0) |
2703 | self:setAccelerationToMotion(0.0, 0.0, 0.0) |
2704 | self.motionInformation.brakeForce = {0.0, 0.0, 0.0} |
2705 | self.motionInformation.isBraking = false |
2706 | end |
resetCameraInputsInformation
DescriptionReset for input managed in update() methodDefinition
resetCameraInputsInformation()Code
2590 | function Player:resetCameraInputsInformation() |
2591 | self.inputInformation.pitchCamera = 0 |
2592 | self.inputInformation.yawCamera = 0 |
2593 | self.inputInformation.crouchState = Player.BUTTONSTATES.RELEASED |
2594 | 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
2581 | function Player:resetInputsInformation() |
2582 | self.inputInformation.moveRight = 0 |
2583 | self.inputInformation.moveForward = 0 |
2584 | self.inputInformation.moveUp = 0 |
2585 | self.inputInformation.runAxis = 0 |
2586 | end |
rotateObject
DescriptionRotates objectDefinition
rotateObject()Code
3005 | function Player:rotateObject(inputValue, axisX, axisY, axisZ) |
3006 | local jointIndex = self.pickedUpObjectJointId |
3007 | local actor = 0 |
3008 | local objectTransform = self.pickUpKinematicHelperNodeChild |
3009 | local rotX, rotY, rotZ = localDirectionToLocal(self.cameraNode, objectTransform, axisX, axisY, axisZ) |
3010 | local dtInSec = g_physicsDt * 0.001 |
3011 | local rotation = math.rad(90.0) * dtInSec * inputValue |
3012 | |
3013 | rotateAboutLocalAxis(objectTransform, rotation, rotX, rotY, rotZ) |
3014 | setJointFrame(jointIndex, actor, objectTransform) |
3015 | 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 |
746 | function Player:setCuttingAnim(isCutting, isHorizontalCut) |
747 | if not isCutting and (self.baseInformation.isUsingChainsawHorizontal or self.baseInformation.isUsingChainsawVertical) then |
748 | self.baseInformation.isUsingChainsawHorizontal = false |
749 | self.baseInformation.isUsingChainsawVertical = false |
750 | elseif isCutting then |
751 | if isHorizontalCut then |
752 | self.baseInformation.isUsingChainsawHorizontal = true |
753 | self.baseInformation.isUsingChainsawVertical = false |
754 | else |
755 | self.baseInformation.isUsingChainsawHorizontal = false |
756 | self.baseInformation.isUsingChainsawVertical = true |
757 | end |
758 | end |
759 | end |
setIKDirty
DescriptionSets all ik chain node to dirty so that they are recalculatedDefinition
setIKDirty()Code
1560 | function Player:setIKDirty() |
1561 | IKUtil.setIKChainDirty(self.ikChains, "rightFoot") |
1562 | IKUtil.setIKChainDirty(self.ikChains, "leftFoot") |
1563 | IKUtil.setIKChainDirty(self.ikChains, "rightArm") |
1564 | IKUtil.setIKChainDirty(self.ikChains, "leftArm") |
1565 | IKUtil.setIKChainDirty(self.ikChains, "spine") |
1566 | end |
setLightIsActive
DescriptionDefinitionsetLightIsActive()Code
2144 | function Player:setLightIsActive(isActive, noEventSend) |
2145 | if isActive ~= self.isLightActive then |
2146 | self.isLightActive = isActive |
2147 | PlayerToggleLightEvent.sendEvent(self, isActive, noEventSend) |
2148 | |
2149 | setVisibility(self.lightNode, isActive) |
2150 | g_soundManager:playSample(self.soundInformation.samples.flashlight) |
2151 | end |
2152 | 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) |
1640 | function Player:setRotation(rotX, rotY) |
1641 | self.rotX = math.min(1.2, math.max(-1.5, rotX)) |
1642 | self.rotY = rotY |
1643 | self.graphicsRotY = rotY |
1644 | self.cameraRotY = rotY |
1645 | self.targetGraphicsRotY = rotY |
1646 | end |
setVisibility
DescriptionSets third person mesh visibilityDefinition
setVisibility(bool visibility)Arguments
bool | visibility | if true will update visibility accordingly. |
1822 | function Player:setVisibility(visibility) |
1823 | if self.meshThirdPerson ~= nil then |
1824 | setVisibility(self.meshThirdPerson, visibility) |
1825 | self.visualInformation:setVisibility(visibility) |
1826 | end |
1827 | 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. |
2796 | function Player:setWalkingLock(isLocked) |
2797 | self.walkingIsLocked = isLocked |
2798 | |
2799 | for _, inputRegistration in pairs(self.inputInformation.registrationList) do |
2800 | if inputRegistration.activeType == Player.INPUT_ACTIVE_TYPE.IS_MOVEMENT then |
2801 | g_inputBinding:setActionEventActive(inputRegistration.eventId, not isLocked) |
2802 | end |
2803 | end |
2804 | end |
setWoodWorkVisibility
DescriptionSets visibility for gloves and helmet. Gloves code is deprecated.Definition
setWoodWorkVisibility(bool visibilityGloves, bool visibilityHelmet)Arguments
bool | visibilityGloves | if true will update visibility of gloves accordingly. |
bool | visibilityHelmet | if true will update visibility of helmet accordingly. |
1833 | function Player:setWoodWorkVisibility(state, uvs) |
1834 | if self.isEntered then |
1835 | self.visualInformation:setProtectiveVisibility(false) |
1836 | end |
1837 | self.visualInformation:setProtectiveVisibility(state) |
1838 | 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 |
1847 | function Player:testScope(x, y, z, coeff) |
1848 | local x1, y1, z1 = getTranslation(self.rootNode) |
1849 | local dist = MathUtil.vector3Length(x1 - x, y1 - y, z1 - z) |
1850 | local clipDist = self.clipDistance |
1851 | if dist < clipDist * clipDist then |
1852 | return true |
1853 | else |
1854 | return false |
1855 | end |
1856 | end |
throwObject
DescriptionThrows an object. Activates dog to fetch a ball if conditions are met.Definition
throwObject()Code
2309 | function Player:throwObject(noEventSend) |
2310 | PlayerThrowObjectEvent.sendEvent(self, noEventSend) |
2311 | if self.pickedUpObject ~= nil and self.pickedUpObjectJointId ~= nil then |
2312 | local pickedUpObject = self.pickedUpObject |
2313 | self:pickUpObject(false) |
2314 | |
2315 | local mass = getMass(pickedUpObject) |
2316 | |
2317 | local v = 8 * (1.1-mass/Player.MAX_PICKABLE_OBJECT_MASS) -- speed between 0.8 and 8.8 based on mass of current object |
2318 | local vx, vy, vz = localDirectionToWorld(self.cameraNode, 0, 0, -v) |
2319 | setLinearVelocity(pickedUpObject, vx, vy, vz) |
2320 | |
2321 | local object = g_currentMission:getNodeObject(pickedUpObject) |
2322 | if object ~= nil then |
2323 | object.thrownFromPosition = {getWorldTranslation(self.rootNode)} |
2324 | |
2325 | if object:isa(DogBall) then |
2326 | local dogHouse = g_currentMission:getDoghouse(self.farmId) |
2327 | if dogHouse ~= nil and dogHouse.dog ~= nil and dogHouse.dog.playersInRange[self.rootNode] then |
2328 | dogHouse.dog:fetchItem(self, object) |
2329 | end |
2330 | end |
2331 | end |
2332 | elseif (self.isObjectInRange and self.lastFoundObject ~= nil) and not self.isCarryingObject then |
2333 | local mass = getMass(self.lastFoundObject) |
2334 | |
2335 | if mass <= Player.MAX_PICKABLE_OBJECT_MASS then |
2336 | local v = 8 * (1.1 - mass / Player.MAX_PICKABLE_OBJECT_MASS) -- speed between 0.8 and 8.8 based on mass of current object |
2337 | local halfSqrt = 0.707106781 |
2338 | -- Add the impulse in 45deg towards the y axis of the camera |
2339 | local vx,vy,vz = localDirectionToWorld(self.cameraNode, 0.0, halfSqrt * v, -halfSqrt * v) |
2340 | setLinearVelocity(self.lastFoundObject, vx, vy, vz) |
2341 | end |
2342 | end |
2343 | end |
unequipHandtool
DescriptionDefinitionunequipHandtool()Code
2242 | function Player:unequipHandtool() |
2243 | self:equipHandtool("", true) |
2244 | 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 |
1132 | function Player:update(dt) |
1133 | self.time = self.time + dt |
1134 | |
1135 | -- 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))) |
1136 | if not self.isEntered and self.isClient and self.isControlled then |
1137 | self:updateFX() |
1138 | end |
1139 | |
1140 | -- check if the player is on ground |
1141 | if self.isServer or self.isEntered then |
1142 | local _, _, isOnGround = getCCTCollisionFlags(self.controllerIndex) |
1143 | self.baseInformation.isOnGroundPhysics = isOnGround |
1144 | end |
1145 | |
1146 | if self.isClient and self.isControlled then |
1147 | self:updateWaterParms() |
1148 | self:updateSound() |
1149 | end |
1150 | |
1151 | if self.isEntered and self.isClient and not g_gui:getIsGuiVisible() then |
1152 | if not g_currentMission.isPlayerFrozen then |
1153 | self:updatePlayerStates() |
1154 | self.playerStateMachine:update(dt) |
1155 | self:recordPositionInformation() |
1156 | self:cameraBob(dt) |
1157 | self:debugDraw() |
1158 | self.playerStateMachine:debugDraw(dt) |
1159 | |
1160 | if not self.walkingIsLocked then |
1161 | self.rotX = self.rotX - self.inputInformation.pitchCamera * g_gameSettings:getValue(GameSettings.SETTING.CAMERA_SENSITIVITY) |
1162 | self.rotY = self.rotY - self.inputInformation.yawCamera * g_gameSettings:getValue(GameSettings.SETTING.CAMERA_SENSITIVITY) |
1163 | |
1164 | self.rotX = math.min(1.2, math.max(-1.5, self.rotX)) |
1165 | setRotation(self.cameraNode, self.rotX, self.rotY, 0) |
1166 | setRotation(self.foliageBendingNode, 0, self.rotY, 0) |
1167 | end |
1168 | self:updateActionEvents() |
1169 | end |
1170 | end |
1171 | |
1172 | if self:hasHandtoolEquipped() then |
1173 | self.baseInformation.currentHandtool:update(dt, self:getIsInputAllowed()) |
1174 | |
1175 | if self.playerStateMachine:isActive("swim") then |
1176 | self:unequipHandtool() |
1177 | end |
1178 | end |
1179 | |
1180 | self:updateInterpolation() |
1181 | |
1182 | if self.isClient and self.isControlled then |
1183 | self:updateRotation(dt) |
1184 | end |
1185 | |
1186 | -- animation |
1187 | if self.isClient and self.isControlled and not self.isEntered then |
1188 | self:updateAnimationParameters(dt) |
1189 | updateConditionalAnimation(self.animationInformation.player, dt) |
1190 | |
1191 | -- Animation Debug |
1192 | --local a,b,c = getWorldTranslation(self.rootNode) |
1193 | --b = b + 1.0 |
1194 | --conditionalAnimationDebugDraw(self.animationInformation.player, a,b,c) |
1195 | end |
1196 | |
1197 | -- objects in front of player |
1198 | self:checkObjectInRange() |
1199 | -- if self.isEntered or (self.isControlled and self.networkInformation.interpolationTime.isDirty) then |
1200 | if self.isEntered or self.networkInformation.interpolationTime.isDirty then |
1201 | self:raiseActive() |
1202 | end |
1203 | |
1204 | if self.isClient and self.isControlled and not self.isEntered and self.networkInformation.rotateObject then |
1205 | self:rotateObject(self.networkInformation.rotateObjectInputV, 1.0, 0.0, 0.0) |
1206 | self:rotateObject(self.networkInformation.rotateObjectInputH, 0.0, 1.0, 0.0) |
1207 | end |
1208 | self:resetCameraInputsInformation() |
1209 | end |
updateActionEvents
DescriptionUpdate action event states and input hint display.Definition
updateActionEvents()Code
1289 | function Player:updateActionEvents() |
1290 | -- light |
1291 | local isDark = g_currentMission.environment.currentHour > g_currentMission.environment.nightStart - 0.5 or g_currentMission.environment.currentHour < g_currentMission.environment.nightEnd + 0.5 |
1292 | local eventIdToggleLight = self.inputInformation.registrationList[InputAction.TOGGLE_LIGHTS_FPS].eventId |
1293 | if self.playerStateMachine:isAvailable("useLight") and isDark then |
1294 | g_inputBinding:setActionEventTextVisibility(eventIdToggleLight, isDark and self.lightNode ~= nil) |
1295 | end |
1296 | |
1297 | local eventList = self.inputInformation.registrationList |
1298 | function disableInput(inputAction) |
1299 | local id = eventList[inputAction].eventId |
1300 | g_inputBinding:setActionEventActive(id, false) |
1301 | g_inputBinding:setActionEventTextVisibility(id, false) |
1302 | end |
1303 | |
1304 | function enableInput(inputAction) |
1305 | local id = eventList[inputAction].eventId |
1306 | g_inputBinding:setActionEventActive(id, true) |
1307 | g_inputBinding:setActionEventTextVisibility(id, true) |
1308 | end |
1309 | |
1310 | disableInput(InputAction.NEXT_HANDTOOL) |
1311 | disableInput(InputAction.PREVIOUS_HANDTOOL) |
1312 | disableInput(InputAction.ACTIVATE_HANDTOOL) |
1313 | disableInput(InputAction.INTERACT) |
1314 | disableInput(InputAction.ACTIVATE_OBJECT) |
1315 | disableInput(InputAction.ENTER) |
1316 | disableInput(InputAction.THROW_OBJECT) |
1317 | disableInput(InputAction.ROTATE_OBJECT_LEFT_RIGHT) |
1318 | disableInput(InputAction.ROTATE_OBJECT_UP_DOWN) |
1319 | |
1320 | -- tools |
1321 | if self.playerStateMachine:isAvailable("cycleHandtool") then |
1322 | enableInput(InputAction.NEXT_HANDTOOL) |
1323 | enableInput(InputAction.PREVIOUS_HANDTOOL) |
1324 | end |
1325 | |
1326 | |
1327 | if self:hasHandtoolEquipped() then |
1328 | enableInput(InputAction.ACTIVATE_HANDTOOL) |
1329 | |
1330 | local eventIdActivateObject = self.inputInformation.registrationList[InputAction.ACTIVATE_OBJECT].eventId |
1331 | if self.playerStateMachine:isAvailable("activateObject") then |
1332 | enableInput(InputAction.ACTIVATE_OBJECT) |
1333 | local activateObjectState = self.playerStateMachine:getState("activateObject") |
1334 | g_inputBinding:setActionEventText(eventIdActivateObject, activateObjectState.activateText) |
1335 | end |
1336 | else |
1337 | |
1338 | if self.playerStateMachine:isAvailable("throw") then |
1339 | enableInput(InputAction.THROW_OBJECT) |
1340 | end |
1341 | |
1342 | local eventIdObjectRotateHorizontally = self.inputInformation.registrationList[InputAction.ROTATE_OBJECT_LEFT_RIGHT].eventId |
1343 | local eventIdObjectRotateVertically = self.inputInformation.registrationList[InputAction.ROTATE_OBJECT_UP_DOWN].eventId |
1344 | if self.isCarryingObject then |
1345 | enableInput(InputAction.ROTATE_OBJECT_LEFT_RIGHT) |
1346 | enableInput(InputAction.ROTATE_OBJECT_UP_DOWN) |
1347 | end |
1348 | |
1349 | local eventIdActivateObject = self.inputInformation.registrationList[InputAction.ACTIVATE_OBJECT].eventId |
1350 | if self.playerStateMachine:isAvailable("activateObject") then |
1351 | enableInput(InputAction.ACTIVATE_OBJECT) |
1352 | local activateObjectState = self.playerStateMachine:getState("activateObject") |
1353 | g_inputBinding:setActionEventText(eventIdActivateObject, activateObjectState.activateText) |
1354 | elseif self.playerStateMachine:isAvailable("animalFeed") then |
1355 | enableInput(InputAction.ACTIVATE_OBJECT) |
1356 | g_inputBinding:setActionEventText(eventIdActivateObject, g_i18n:getText("action_feedAnimal")) |
1357 | elseif self.playerStateMachine:isAvailable("animalPet") then |
1358 | enableInput(InputAction.ACTIVATE_OBJECT) |
1359 | g_inputBinding:setActionEventText(eventIdActivateObject, g_i18n:getText("action_petAnimal")) |
1360 | end |
1361 | |
1362 | local eventIdInteract = self.inputInformation.registrationList[InputAction.INTERACT].eventId |
1363 | if self.playerStateMachine:isAvailable("drop") then |
1364 | g_inputBinding:setActionEventText(eventIdInteract, g_i18n:getText("action_dropObject")) |
1365 | enableInput(InputAction.INTERACT) |
1366 | elseif self.playerStateMachine:isAvailable("pickup") then |
1367 | g_inputBinding:setActionEventText(eventIdInteract, g_i18n:getText("action_pickUpObject")) |
1368 | enableInput(InputAction.INTERACT) |
1369 | elseif self.playerStateMachine:isAvailable("animalInteract") or self.playerStateMachine:isActive("animalInteract") then |
1370 | local animalInteractState = self.playerStateMachine:getState("animalInteract") |
1371 | local animalInteractText = string.format(g_i18n:getText("action_interactAnimal"), animalInteractState.interactText) |
1372 | g_inputBinding:setActionEventText(eventIdInteract, animalInteractText) |
1373 | enableInput(InputAction.INTERACT) |
1374 | elseif self.inputInformation.interactState == Player.BUTTONSTATES.RELEASED then |
1375 | disableInput(InputAction.INTERACT) |
1376 | end |
1377 | end |
1378 | |
1379 | -- enter vehicle or ride animal |
1380 | self.canRideAnimal = self.playerStateMachine:isAvailable("animalRide") |
1381 | self.canEnterVehicle = g_currentMission.interactiveVehicleInRange and g_currentMission.interactiveVehicleInRange:getIsEnterable() |
1382 | local vehicleIsRideable = self.canEnterVehicle and SpecializationUtil.hasSpecialization(Rideable, g_currentMission.interactiveVehicleInRange.specializations) |
1383 | local eventIdEnter = self.inputInformation.registrationList[InputAction.ENTER].eventId |
1384 | if self.canEnterVehicle and not vehicleIsRideable then |
1385 | g_inputBinding:setActionEventText(eventIdEnter, g_i18n:getText("button_enterVehicle")) |
1386 | enableInput(InputAction.ENTER) |
1387 | elseif self.canRideAnimal or vehicleIsRideable then |
1388 | local rideableName = "" |
1389 | if self.canRideAnimal then |
1390 | local rideState = self.playerStateMachine:getState("animalRide") |
1391 | rideableName = rideState:getRideableName() |
1392 | elseif vehicleIsRideable then |
1393 | rideableName = g_currentMission.interactiveVehicleInRange:getFullName() |
1394 | end |
1395 | g_inputBinding:setActionEventText(eventIdEnter, string.format(g_i18n:getText("action_rideAnimal"), rideableName)) |
1396 | enableInput(InputAction.ENTER) |
1397 | end |
1398 | |
1399 | -- debug movements |
1400 | local eventIdDebugFlyToggle = self.inputInformation.registrationList[InputAction.DEBUG_PLAYER_ENABLE].eventId |
1401 | g_inputBinding:setActionEventActive(eventIdDebugFlyToggle, g_flightAndNoHUDKeysEnabled) |
1402 | local eventIdDebugFlyUpDown = self.inputInformation.registrationList[InputAction.DEBUG_PLAYER_UP_DOWN].eventId |
1403 | g_inputBinding:setActionEventActive(eventIdDebugFlyUpDown, g_flightAndNoHUDKeysEnabled) |
1404 | end |
updateAnimationParameters
DescriptionUpdates the parameters that will drive the animationDefinition
updateAnimationParameters(float dt)Arguments
float | dt | delta time in ms |
1060 | function Player:updateAnimationParameters(dt) |
1061 | local dx = (self.networkInformation.interpolatorPosition.targetPositionX - self.networkInformation.interpolatorPosition.lastPositionX) |
1062 | local dy = (self.networkInformation.interpolatorPosition.targetPositionY - self.networkInformation.interpolatorPosition.lastPositionY) |
1063 | local dz = (self.networkInformation.interpolatorPosition.targetPositionZ - self.networkInformation.interpolatorPosition.lastPositionZ) |
1064 | local vx = dx / (self.networkInformation.interpolationTime.interpolationDuration * 0.001) |
1065 | local vy = dy / (self.networkInformation.interpolationTime.interpolationDuration * 0.001) |
1066 | local vz = dz / (self.networkInformation.interpolationTime.interpolationDuration * 0.001) |
1067 | local dirX, dirZ = math.sin(self.graphicsRotY), math.cos(self.graphicsRotY) |
1068 | local estimatedForwardVelocity = vx * dirX + vz * dirZ |
1069 | -- @see using calculation in Player:updateRotation() for a less unstable speed |
1070 | -- self.lastEstimatedForwardVelocity = self.lastEstimatedForwardVelocity * 0.5 + estimatedForwardVelocity * 0.5 |
1071 | |
1072 | if self.baseInformation.animDt ~= nil and self.baseInformation.animDt ~= 0 then |
1073 | self.animationInformation.oldYaw = self.animationInformation.newYaw |
1074 | self.animationInformation.newYaw = self.cameraRotY |
1075 | self.animationInformation.estimatedYawVelocity = MathUtil.getAngleDifference(self.animationInformation.newYaw, self.animationInformation.oldYaw) / (self.baseInformation.animDt * 0.001) |
1076 | self.baseInformation.animDt = 0 |
1077 | end |
1078 | |
1079 | local params = self.animationInformation.parameters |
1080 | params.forwardVelocity.value = self.lastEstimatedForwardVelocity |
1081 | params.verticalVelocity.value = vy |
1082 | params.yawVelocity.value = self.animationInformation.estimatedYawVelocity |
1083 | params.absYawVelocity.value = math.abs(self.animationInformation.estimatedYawVelocity) |
1084 | params.onGround.value = self.baseInformation.isOnGround |
1085 | params.inWater.value = self.baseInformation.isInWater |
1086 | params.isCrouched.value = self.baseInformation.isCrouched |
1087 | params.absForwardVelocity.value = math.abs(self.lastEstimatedForwardVelocity) |
1088 | params.isCloseToGround.value = self.baseInformation.isCloseToGround |
1089 | params.isUsingChainsawHorizontal.value = self.baseInformation.isUsingChainsawHorizontal |
1090 | params.isUsingChainsawVertical.value = self.baseInformation.isUsingChainsawVertical |
1091 | |
1092 | for _, parameter in pairs(self.animationInformation.parameters) do |
1093 | if parameter.type == 0 then |
1094 | setConditionalAnimationBoolValue(self.animationInformation.player, parameter.id, parameter.value) |
1095 | elseif parameter.type == 1 then |
1096 | setConditionalAnimationFloatValue(self.animationInformation.player, parameter.id, parameter.value) |
1097 | end |
1098 | end |
1099 | end |
updateFX
DescriptionUpdate particle FX.Definition
updateFX()Code
2467 | function Player:updateFX() |
2468 | -- swim |
2469 | -- if self.baseInformation.isInWater then -- and self.motionInformation.justMoved then |
2470 | -- local x, _, z = getWorldTranslation(self.rootNode) |
2471 | |
2472 | -- setWorldTranslation(self.particleSystemsInformation.swimNode, x, g_currentMission.waterY, z) |
2473 | -- ParticleUtil.setEmittingState(self.particleSystemsInformation.systems.swim, true) |
2474 | -- else |
2475 | -- ParticleUtil.resetNumOfEmittedParticles(self.particleSystemsInformation.systems.swim) |
2476 | -- ParticleUtil.setEmittingState(self.particleSystemsInformation.systems.swim, false) |
2477 | -- end |
2478 | |
2479 | -- plunge |
2480 | if self.baseInformation.plungedInWater then |
2481 | local x, _, z = getWorldTranslation(self.rootNode) |
2482 | |
2483 | setWorldTranslation(self.particleSystemsInformation.plungeNode, x, g_currentMission.waterY, z) |
2484 | ParticleUtil.resetNumOfEmittedParticles(self.particleSystemsInformation.systems.plunge) |
2485 | ParticleUtil.setEmittingState(self.particleSystemsInformation.systems.plunge, true) |
2486 | end |
2487 | end |
updateInterpolation
DescriptionUpdates interpolations for physics, camera and positionDefinition
updateInterpolation()Code
1448 | function Player:updateInterpolation() |
1449 | if self.isControlled then |
1450 | local needsCameraInterp = self.isServer and not self.isEntered |
1451 | local needsPositionInterp = self.isClient |
1452 | |
1453 | if needsCameraInterp or needsPositionInterp then |
1454 | if self.networkInformation.interpolationTime.isDirty then |
1455 | self.networkInformation.interpolationTime:update(g_physicsDtUnclamped) |
1456 | if needsCameraInterp then |
1457 | local qx, qy, qz, qw = self.networkInformation.interpolatorQuaternion:getInterpolatedValues(self.networkInformation.interpolationTime.interpolationAlpha) |
1458 | |
1459 | setQuaternion(self.cameraNode, qx, qy, qz, qw) |
1460 | end |
1461 | if needsPositionInterp then |
1462 | local x, y, z = self.networkInformation.interpolatorPosition:getInterpolatedValues(self.networkInformation.interpolationTime.interpolationAlpha) |
1463 | setTranslation(self.graphicsRootNode, x, y - self.baseInformation.capsuleTotalHeight * 0.5, z) |
1464 | local isOnGroundFloat = self.networkInformation.interpolatorOnGround:getInterpolatedValue(self.networkInformation.interpolationTime.interpolationAlpha) |
1465 | self.baseInformation.isOnGround = isOnGroundFloat > 0.9 |
1466 | self.baseInformation.isCloseToGround = isOnGroundFloat > 0.5 |
1467 | end |
1468 | end |
1469 | end |
1470 | end |
1471 | end |
updateInterpolationTick
DescriptionUpdates interpolations for physics, camera and positionDefinition
updateInterpolationTick()Code
1408 | function Player:updateInterpolationTick() |
1409 | if self.isEntered then |
1410 | local xt, yt, zt = getTranslation(self.rootNode) |
1411 | -- Reuse the existing target position if the change is very small to avoid jitter |
1412 | local interpPos = self.networkInformation.interpolatorPosition |
1413 | 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 |
1414 | xt, yt, zt = interpPos.targetPositionX, interpPos.targetPositionY, interpPos.targetPositionZ |
1415 | end |
1416 | self.networkInformation.interpolatorPosition:setTargetPosition(xt, yt, zt) |
1417 | |
1418 | if self.baseInformation.isOnGroundPhysics then |
1419 | self.networkInformation.interpolatorOnGround:setTargetValue(1.0) |
1420 | else |
1421 | self.networkInformation.interpolatorOnGround:setTargetValue(0.0) |
1422 | end |
1423 | self.networkInformation.interpolationTime:startNewPhase(75) |
1424 | elseif self.networkInformation.updateTargetTranslationPhysicsIndex >= 0 then |
1425 | local xt, yt, zt = getTranslation(self.rootNode) |
1426 | if getIsPhysicsUpdateIndexSimulated(self.networkInformation.updateTargetTranslationPhysicsIndex) then |
1427 | self.networkInformation.updateTargetTranslationPhysicsIndex = -1 |
1428 | else |
1429 | -- Reuse the existing target position if the change is very small to avoid jitter |
1430 | local interpPos = self.networkInformation.interpolatorPosition |
1431 | 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 |
1432 | xt, yt, zt = interpPos.targetPositionX, interpPos.targetPositionY, interpPos.targetPositionZ |
1433 | end |
1434 | end |
1435 | self.networkInformation.interpolatorPosition:setTargetPosition(xt, yt, zt) |
1436 | if self.baseInformation.isOnGroundPhysics then |
1437 | self.networkInformation.interpolatorOnGround:setTargetValue(1.0) |
1438 | else |
1439 | self.networkInformation.interpolatorOnGround:setTargetValue(0.0) |
1440 | end |
1441 | self.networkInformation.interpolatorQuaternion:setTargetQuaternion(self.networkInformation.interpolatorQuaternion.targetQuaternionX, self.networkInformation.interpolatorQuaternion.targetQuaternionY, self.networkInformation.interpolatorQuaternion.targetQuaternionZ, self.networkInformation.interpolatorQuaternion.targetQuaternionW) |
1442 | self.networkInformation.interpolationTime:startNewPhase(75) |
1443 | end |
1444 | end |
updateKinematic
DescriptionUpdates player movement depending on inputs (run, crouch, swim) and apply gravityDefinition
updateKinematic()Code
2710 | function Player:updateKinematic(dt) |
2711 | local dtInSec = dt * 0.001 |
2712 | local inputX = self.inputInformation.moveRight |
2713 | local inputZ = self.inputInformation.moveForward |
2714 | if inputX ~= 0.0 or inputZ ~= 0.0 then |
2715 | local normInputX, normInputZ = MathUtil.vector2Normalize(inputX, inputZ) |
2716 | self.motionInformation.currentWorldDirX, _, self.motionInformation.currentWorldDirZ = localDirectionToWorld(self.cameraNode, normInputX, 0.0, normInputZ) |
2717 | self.motionInformation.currentWorldDirX, self.motionInformation.currentWorldDirZ = MathUtil.vector2Normalize(self.motionInformation.currentWorldDirX, self.motionInformation.currentWorldDirZ) |
2718 | end |
2719 | local desiredSpeed = self:getDesiredSpeed() |
2720 | local desiredSpeedX = self.motionInformation.currentWorldDirX * desiredSpeed |
2721 | local desiredSpeedZ = self.motionInformation.currentWorldDirZ * desiredSpeed |
2722 | |
2723 | local speedChangeX = (desiredSpeedX - self.motionInformation.currentSpeedX) |
2724 | local speedChangeZ = (desiredSpeedZ - self.motionInformation.currentSpeedZ) |
2725 | |
2726 | if not self.baseInformation.isOnGround then |
2727 | -- reduce acceleration when in the air |
2728 | speedChangeX = speedChangeX * 0.2 |
2729 | speedChangeZ = speedChangeZ * 0.2 |
2730 | end |
2731 | |
2732 | self.motionInformation.currentSpeedX = self.motionInformation.currentSpeedX + speedChangeX |
2733 | self.motionInformation.currentSpeedZ = self.motionInformation.currentSpeedZ + speedChangeZ |
2734 | self.motionInformation.currentSpeed = math.sqrt(self.motionInformation.currentSpeedX * self.motionInformation.currentSpeedX + self.motionInformation.currentSpeedZ * self.motionInformation.currentSpeedZ) |
2735 | |
2736 | local movementX = self.motionInformation.currentSpeedX * dtInSec |
2737 | local movementY = 0.0 |
2738 | local movementZ = self.motionInformation.currentSpeedZ * dtInSec |
2739 | |
2740 | -- Swim adjustment |
2741 | local _, y, _ = getWorldTranslation(self.rootNode) |
2742 | local deltaWater = y - g_currentMission.waterY - self.baseInformation.capsuleTotalHeight * 0.5 |
2743 | local waterLevel = self.baseInformation.waterLevel |
2744 | |
2745 | local distToWaterLevel = deltaWater - waterLevel |
2746 | |
2747 | if distToWaterLevel > 0.001 then |
2748 | -- Update gravity / vertical movement |
2749 | local gravityFactor = 3.0 -- for falling faster |
2750 | local gravitySpeedChange = gravityFactor * self.motionInformation.gravity * dtInSec |
2751 | self.motionInformation.currentSpeedY = math.max(self.motionInformation.currentSpeedY + gravitySpeedChange, self.motionInformation.gravity * 7.0) -- clamp after 7s of falling |
2752 | if distToWaterLevel < self.baseInformation.capsuleTotalHeight * 0.5 then |
2753 | -- hack to reduce unsteability in low framerate |
2754 | movementY = math.max(self.motionInformation.currentSpeedY * dtInSec, -distToWaterLevel * 0.5) |
2755 | else |
2756 | movementY = math.max(self.motionInformation.currentSpeedY * dtInSec, -distToWaterLevel) |
2757 | end |
2758 | self.motionInformation.currentSpeedY = movementY / math.max(dtInSec, 0.000001) -- calc actual speed with clamped movement |
2759 | elseif distToWaterLevel < -0.01 then |
2760 | local buoyancySpeed = -self.motionInformation.gravity |
2761 | movementY = math.min(buoyancySpeed * dtInSec, -distToWaterLevel) |
2762 | self.motionInformation.currentSpeedY = movementY / math.max(dtInSec, 0.000001) -- calc actual speed with clamped movement |
2763 | else |
2764 | self.motionInformation.currentSpeedY = 0.0 |
2765 | end |
2766 | |
2767 | self:movePlayer(dt, movementX, movementY, movementZ) |
2768 | end |
updateNetworkMovementHistory
DescriptionDefinitionupdateNetworkMovementHistory()Code
1475 | function Player:updateNetworkMovementHistory() |
1476 | if self.isEntered and self.isClient then |
1477 | self:raiseDirtyFlags(self.networkInformation.dirtyFlag) |
1478 | elseif self.isServer and not self.isEntered and self.isControlled then |
1479 | -- find the latest index, which is already simulated now |
1480 | local latestSimulatedIndex = -1 |
1481 | while self.networkInformation.history[1] ~= nil and getIsPhysicsUpdateIndexSimulated(self.networkInformation.history[1].physicsIndex) do |
1482 | latestSimulatedIndex = self.networkInformation.history[1].index |
1483 | table.remove(self.networkInformation.history, 1) |
1484 | end |
1485 | if latestSimulatedIndex >= 0 then |
1486 | self.networkInformation.sendIndex = latestSimulatedIndex |
1487 | self:raiseDirtyFlags(self.networkInformation.dirtyFlag) |
1488 | end |
1489 | end |
1490 | end |
updatePlayerStates
DescriptionUpdates player state machineDefinition
updatePlayerStates()Code
2772 | function Player:updatePlayerStates() |
2773 | if self.playerStateMachine:isAvailable("fall") then |
2774 | self.playerStateMachine:activateState("fall") |
2775 | end |
2776 | |
2777 | if self.baseInformation.isInWater and self.playerStateMachine:isAvailable("swim") then |
2778 | self.playerStateMachine:activateState("swim") |
2779 | self.playerStateMachine:deactivateState("crouch") |
2780 | end |
2781 | |
2782 | if (self.inputInformation.moveForward ~= 0) or (self.inputInformation.moveRight ~= 0) then |
2783 | if (self.inputInformation.runAxis > 0.0) and self.playerStateMachine:isAvailable("run") then |
2784 | self.playerStateMachine:activateState("run") |
2785 | elseif self.playerStateMachine:isAvailable("walk") then |
2786 | self.playerStateMachine:activateState("walk") |
2787 | end |
2788 | else |
2789 | self.playerStateMachine:activateState("idle") |
2790 | end |
2791 | end |
updatePlayHandToolStopSample
DescriptionDefinitionupdatePlayHandToolStopSample()Code
2290 | function Player:updatePlayHandToolStopSample() |
2291 | if self.soundInformation.deleteHandtoolStopSampleAfterPlay and self.soundInformation.samples.handtoolStop.soundSample ~= nil and not g_soundManager:getIsSamplePlaying(self.soundInformation.samples.handtoolStop) then |
2292 | self:deleteHandToolStopSample() |
2293 | end |
2294 | end |
updateRotation
DescriptionUpdates rotation of player avatar over the networkDefinition
updateRotation(float dt)Arguments
float | dt | delta time in ms |
1495 | function Player:updateRotation(dt) |
1496 | if not self.isEntered then |
1497 | local animDt = 60 |
1498 | self.animUpdateTime = self.animUpdateTime + dt |
1499 | if self.animUpdateTime > animDt then |
1500 | if self.isServer then |
1501 | local x, _, z = localDirectionToLocal(self.cameraNode, getParent(self.cameraNode), 0, 0, 1) |
1502 | local alpha = math.atan2(x, z) |
1503 | self.cameraRotY = alpha |
1504 | end |
1505 | |
1506 | local x, y, z = getTranslation(self.graphicsRootNode) |
1507 | local dx, _, dz = x - self.lastAnimPosX, y - self.lastAnimPosY, z - self.lastAnimPosZ |
1508 | local dirX, dirZ = -math.sin(self.cameraRotY), -math.cos(self.cameraRotY) |
1509 | local movementDist = dx * dirX + dz * dirZ -- Note: |dir| = 1 |
1510 | |
1511 | if (dx * dx + dz * dz) < 0.001 then |
1512 | self.targetGraphicsRotY = self.cameraRotY + math.rad(180.0) |
1513 | else |
1514 | if movementDist > -0.001 then |
1515 | self.targetGraphicsRotY = math.atan2(dx, dz) |
1516 | else |
1517 | self.targetGraphicsRotY = math.atan2(-dx, -dz) |
1518 | end |
1519 | end |
1520 | |
1521 | dirX, dirZ = -math.sin(self.targetGraphicsRotY), -math.cos(self.targetGraphicsRotY) |
1522 | movementDist = dx * dirX + dz * dirZ -- Note: |dir| = 1 |
1523 | movementDist = self.walkDistance * 0.2 + movementDist * 0.8 |
1524 | self.walkDistance = movementDist |
1525 | self.lastEstimatedForwardVelocity = -movementDist / (self.animUpdateTime * 0.001) |
1526 | |
1527 | self.lastAnimPosX = x |
1528 | self.lastAnimPosY = y |
1529 | self.lastAnimPosZ = z |
1530 | |
1531 | self.baseInformation.animDt = self.animUpdateTime |
1532 | self.animUpdateTime = 0 |
1533 | end |
1534 | |
1535 | self.targetGraphicsRotY = MathUtil.normalizeRotationForShortestPath(self.targetGraphicsRotY, self.graphicsRotY) |
1536 | local maxDeltaRotY = math.rad(0.5) * dt |
1537 | self.graphicsRotY = math.min(math.max(self.targetGraphicsRotY, self.graphicsRotY - maxDeltaRotY), self.graphicsRotY + maxDeltaRotY) |
1538 | |
1539 | setRotation(self.skeletonRootNode, 0, self.graphicsRotY, 0) |
1540 | end |
1541 | end |
updateSound
DescriptionUpdate sound for the player: steps (when crouch, walk, run), swim, plungeDefinition
updateSound()Code
2388 | function Player:updateSound() |
2389 | -- Foot steps |
2390 | local distanceToCheck = -1.0 |
2391 | local forwardVel = 0.0 |
2392 | |
2393 | if not self.isEntered then |
2394 | forwardVel = getConditionalAnimationFloatValue(self.animationInformation.player, self.animationInformation.parameters.absForwardVelocity.id) |
2395 | if self.playerStateMachine:isActive("crouch") then |
2396 | distanceToCheck = self.soundInformation.distancePerFootstep.crouch |
2397 | elseif math.abs(forwardVel) <= self.motionInformation.maxWalkingSpeed then |
2398 | distanceToCheck = self.soundInformation.distancePerFootstep.walk |
2399 | elseif math.abs(forwardVel) > self.motionInformation.maxWalkingSpeed then |
2400 | distanceToCheck = self.soundInformation.distancePerFootstep.run |
2401 | end |
2402 | else |
2403 | forwardVel = math.abs(self.motionInformation.currentSpeed) |
2404 | if self.playerStateMachine:isActive("crouch") then |
2405 | distanceToCheck = self.soundInformation.distancePerFootstep.crouch |
2406 | elseif self.playerStateMachine:isActive("walk") then |
2407 | distanceToCheck = self.soundInformation.distancePerFootstep.walk |
2408 | elseif self.playerStateMachine:isActive("run") then |
2409 | distanceToCheck = self.soundInformation.distancePerFootstep.run |
2410 | end |
2411 | end |
2412 | |
2413 | local isSwimming = self.playerStateMachine:isActive("swim") |
2414 | if distanceToCheck > 0.0 or isSwimming then |
2415 | local delta = self.motionInformation.coveredGroundDistance - self.soundInformation.distanceSinceLastFootstep |
2416 | delta = delta - distanceToCheck |
2417 | |
2418 | if delta > 0 or isSwimming then |
2419 | local wx, wy, wz = getWorldTranslation(self.rootNode) |
2420 | local sample, shallowWater = self:getCurrentSurfaceSound(wx, wy, wz) |
2421 | |
2422 | if not self.baseInformation.isInWater then |
2423 | if g_soundManager:getIsSamplePlaying(self.soundInformation.samples.swim) then |
2424 | g_soundManager:stopSample(self.soundInformation.samples.swim) |
2425 | end |
2426 | if g_soundManager:getIsSamplePlaying(self.soundInformation.samples.swimIdle) then |
2427 | g_soundManager:stopSample(self.soundInformation.samples.swimIdle) |
2428 | end |
2429 | end |
2430 | |
2431 | if self.baseInformation.isInWater and not shallowWater then |
2432 | if math.abs(forwardVel) < (self.motionInformation.maxSwimmingSpeed * 0.75) then |
2433 | if g_soundManager:getIsSamplePlaying(self.soundInformation.samples.swim) then |
2434 | g_soundManager:stopSample(self.soundInformation.samples.swim) |
2435 | end |
2436 | if not g_soundManager:getIsSamplePlaying(self.soundInformation.samples.swimIdle) then |
2437 | g_soundManager:playSample(self.soundInformation.samples.swimIdle) |
2438 | end |
2439 | else |
2440 | if g_soundManager:getIsSamplePlaying(self.soundInformation.samples.swimIdle) then |
2441 | g_soundManager:stopSample(self.soundInformation.samples.swimIdle) |
2442 | end |
2443 | if not g_soundManager:getIsSamplePlaying(self.soundInformation.samples.swim) then |
2444 | g_soundManager:playSample(self.soundInformation.samples.swim) |
2445 | end |
2446 | end |
2447 | else |
2448 | if sample ~= nil then |
2449 | g_soundManager:playSample(sample) |
2450 | end |
2451 | end |
2452 | self.soundInformation.distanceSinceLastFootstep = self.motionInformation.coveredGroundDistance + delta |
2453 | end |
2454 | end |
2455 | |
2456 | -- plunge |
2457 | if self.baseInformation.plungedInWater then |
2458 | g_soundManager:playSample(self.soundInformation.samples.plunge) |
2459 | end |
2460 | |
2461 | -- handTools |
2462 | self:updatePlayHandToolStopSample() |
2463 | 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 |
1242 | function Player:updateTick(dt) |
1243 | if self.isEntered and not g_gui:getIsGuiVisible() and not g_currentMission.isPlayerFrozen then |
1244 | self:updateKinematic(dt) |
1245 | end |
1246 | |
1247 | self.playerStateMachine:updateTick(dt) |
1248 | |
1249 | if self:hasHandtoolEquipped() then |
1250 | self.baseInformation.currentHandtool:updateTick(dt, self:getIsInputAllowed()) |
1251 | end |
1252 | self:updateNetworkMovementHistory() |
1253 | self:updateInterpolationTick() |
1254 | |
1255 | self:resetInputsInformation() |
1256 | |
1257 | |
1258 | -- ------------------------- |
1259 | -- @todo: check and add again |
1260 | -- ------------------------- |
1261 | -- local xt, yt, zt = getTranslation(self.rootNode) |
1262 | -- --[[ |
1263 | -- if GS_PLATFORM_TYPE == GS_PLATFORM_TYPE_PS4 or GS_PLATFORM_TYPE == GS_PLATFORM_TYPE_XBOXONE then |
1264 | -- xt = xt + self.movementX |
1265 | -- zt = zt + self.movementZ |
1266 | -- yt = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, xt, 300, zt) + self.height |
1267 | -- setTranslation(self.rootNode, xt, yt, zt) |
1268 | -- end |
1269 | -- --]] |
1270 | -- ------------------------- |
1271 | if self.isServer and self.isControlled then |
1272 | if GS_PLATFORM_TYPE ~= GS_PLATFORM_TYPE_PC then |
1273 | local x, y, z = getTranslation(self.rootNode) |
1274 | local paramsXZ = g_currentMission.vehicleXZPosCompressionParams |
1275 | if not NetworkUtil.getIsWorldPositionInCompressionRange(x, paramsXZ) or |
1276 | not NetworkUtil.getIsWorldPositionInCompressionRange(z, paramsXZ) or |
1277 | getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, y, z) > y + 20 |
1278 | then |
1279 | self:moveTo(g_currentMission.playerStartX, g_currentMission.playerStartY, g_currentMission.playerStartZ, g_currentMission.playerStartIsAbsolute, false) |
1280 | return |
1281 | end |
1282 | end |
1283 | end |
1284 | -- ------------------------- |
1285 | end |
updateWaterParms
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
updateWaterParms()Code
1103 | function Player:updateWaterParms() |
1104 | local _, y, _ = getWorldTranslation(self.rootNode) |
1105 | local deltaWater = y - g_currentMission.waterY - self.baseInformation.capsuleTotalHeight * 0.5 |
1106 | local waterLevel = self.baseInformation.waterLevel |
1107 | local velocityY = 0.0 |
1108 | |
1109 | if deltaWater < -50 then |
1110 | return |
1111 | end |
1112 | |
1113 | if not self.isEntered then |
1114 | velocityY = self.animationInformation.parameters.verticalVelocity.value |
1115 | else |
1116 | velocityY = self.motionInformation.currentSpeedY |
1117 | end |
1118 | |
1119 | self.baseInformation.wasInWater = self.baseInformation.isInWater |
1120 | self.baseInformation.isInWater = deltaWater <= waterLevel |
1121 | |
1122 | if not self.baseInformation.wasInWater and self.baseInformation.isInWater and velocityY < self.baseInformation.plungedYVelocityThreshold then |
1123 | self.baseInformation.plungedInWater = true |
1124 | else |
1125 | self.baseInformation.plungedInWater = false |
1126 | end |
1127 | end |
writeStream
DescriptionWrites in network streamDefinition
writeStream(integer streamId, table connection)Arguments
integer | streamId | id of the stream to read |
table | connection | connection information |
805 | function Player:writeStream(streamId, connection) |
806 | Player:superClass().writeStream(self, streamId) |
807 | streamWriteBool(streamId, connection == self.networkInformation.creatorConnection) |
808 | streamWriteString(streamId, NetworkUtil.convertToNetworkFilename(self.xmlFilename)) |
809 | local x, y, z=getTranslation(self.rootNode) |
810 | streamWriteFloat32(streamId, x) |
811 | streamWriteFloat32(streamId, y) |
812 | streamWriteFloat32(streamId, z) |
813 | streamWriteBool(streamId, self.isControlled) |
814 | self.visualInformation:writeStream(streamId, connection) |
815 | streamWriteUIntN(streamId, self.farmId, FarmManager.FARM_ID_SEND_NUM_BITS) |
816 | |
817 | streamWriteBool(streamId, self.isLightActive) |
818 | |
819 | local hasHandtool = self:hasHandtoolEquipped() |
820 | streamWriteBool(streamId, hasHandtool) |
821 | if hasHandtool then |
822 | streamWriteString(streamId, NetworkUtil.convertToNetworkFilename(self.baseInformation.currentHandtool.configFileName)) |
823 | end |
824 | 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 |
974 | function Player:writeUpdateStream(streamId, connection, dirtyMask) |
975 | if not connection:getIsServer() then |
976 | -- server code (send data to client) |
977 | local x, y, z = getTranslation(self.rootNode) |
978 | --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)) |
979 | streamWriteFloat32(streamId, x) |
980 | streamWriteFloat32(streamId, y) |
981 | streamWriteFloat32(streamId, z) |
982 | |
983 | local x, _, z = localDirectionToLocal(self.cameraNode, getParent(self.cameraNode), 0, 0, 1) |
984 | local alpha = math.atan2(x, z) |
985 | streamWriteFloat32(streamId, alpha) |
986 | |
987 | streamWriteBool(streamId, self.isObjectInRange) |
988 | if self.isObjectInRange then |
989 | streamWriteFloat32(streamId, self.lastFoundObjectMass) |
990 | end |
991 | streamWriteBool(streamId, self.isCarryingObject) |
992 | streamWriteBool(streamId, self.baseInformation.isOnGroundPhysics) |
993 | local isOwner = connection == self.networkInformation.creatorConnection |
994 | if isOwner then |
995 | streamWriteInt32(streamId, self.networkInformation.sendIndex) |
996 | -- [animation] |
997 | local isCrouching = self.baseInformation.isCrouched |
998 | streamWriteBool(streamId, isCrouching) |
999 | -- |
1000 | else |
1001 | streamWriteBool(streamId, self.isControlled) |
1002 | -- [animation] |
1003 | local isCrouching = self.baseInformation.isCrouched or self.playerStateMachine:isActive("crouch") |
1004 | streamWriteBool(streamId, isCrouching) |
1005 | -- |
1006 | end |
1007 | else |
1008 | -- client code (send data to server) |
1009 | if self.isOwner then |
1010 | -- sending translation information to the server and reset the translations accumulated over the update() calls |
1011 | streamWriteFloat32(streamId, self.networkInformation.tickTranslation[1]) |
1012 | streamWriteFloat32(streamId, self.networkInformation.tickTranslation[2]) |
1013 | streamWriteFloat32(streamId, self.networkInformation.tickTranslation[3]) |
1014 | self.networkInformation.tickTranslation[1] = 0.0 |
1015 | self.networkInformation.tickTranslation[2] = 0.0 |
1016 | self.networkInformation.tickTranslation[3] = 0.0 |
1017 | local x, y, z, w = getQuaternion(self.cameraNode) |
1018 | streamWriteFloat32(streamId, x) -- ? ToDo: Utils.writeCompressedQuaternion() |
1019 | streamWriteFloat32(streamId, y) |
1020 | streamWriteFloat32(streamId, z) |
1021 | streamWriteFloat32(streamId, w) |
1022 | |
1023 | streamWriteInt32(streamId, self.networkInformation.index) |
1024 | streamWriteBool(streamId, self.isControlled) |
1025 | -- [animation] |
1026 | local isCrouching = self.playerStateMachine:isActive("crouch") |
1027 | streamWriteBool(streamId, isCrouching) |
1028 | -- |
1029 | if self.isCarryingObject then |
1030 | streamWriteBool(streamId, self.networkInformation.rotateObject) |
1031 | if self.networkInformation.rotateObject then |
1032 | streamWriteFloat32(streamId, self.networkInformation.rotateObjectInputH) |
1033 | streamWriteFloat32(streamId, self.networkInformation.rotateObjectInputV) |
1034 | end |
1035 | end |
1036 | end |
1037 | end |
1038 | end |