LUADOC - Farming Simulator 19

Script v1.7.1.0

Engine v1.7.1.0

Foundation Reference

Enterable

Description
This specialization enables the player to enter a vehicle. It also loads cameras and player character
Functions

actionEventActivateObject

Description
Definition
actionEventActivateObject()
Code
1294function Enterable.actionEventActivateObject(self, actionName, inputValue, callbackState, isAnalog)
1295 -- take an object which is active-able and was added latest
1296 for key, object in pairs(g_currentMission.activatableObjects) do
1297 if object:getIsActivatable() then
1298 g_currentMission.activatableObjects[key] = nil
1299
1300 object:onActivateObject()
1301
1302 for _, v in pairs(g_currentMission.activateListeners) do
1303 v:onActivateObject(object)
1304 end
1305 break
1306 end
1307 end
1308end

actionEventCameraSwitch

Description
Definition
actionEventCameraSwitch()
Code
1257function Enterable.actionEventCameraSwitch(self, actionName, inputValue, callbackState, isAnalog)
1258 local spec = self.spec_enterable
1259 self:setActiveCameraIndex(spec.camIndex + 1)
1260end

actionEventCameraZoomIn

Description
Definition
actionEventCameraZoomIn()
Code
1264function Enterable.actionEventCameraZoomIn(self, actionName, inputValue, callbackState, isAnalog, isMouse)
1265 local spec = self.spec_enterable
1266 local offset = -0.2
1267 if isMouse then -- mouse wheel zoom, must use larger value because of engine input handling
1268 offset = offset * InputBinding.MOUSE_WHEEL_INPUT_FACTOR
1269 end
1270
1271 spec.activeCamera:zoomSmoothly(offset)
1272end

actionEventCameraZoomOut

Description
Definition
actionEventCameraZoomOut()
Code
1276function Enterable.actionEventCameraZoomOut(self, actionName, inputValue, callbackState, isAnalog, isMouse)
1277 local spec = self.spec_enterable
1278 local offset = 0.2
1279 if isMouse then -- mouse wheel zoom, must use larger value because of engine input handling
1280 offset = offset * InputBinding.MOUSE_WHEEL_INPUT_FACTOR
1281 end
1282
1283 spec.activeCamera:zoomSmoothly(offset)
1284end

actionEventLeave

Description
Definition
actionEventLeave()
Code
1247function Enterable.actionEventLeave(self, actionName, inputValue, callbackState, isAnalog)
1248 local spec = self.spec_enterable
1249 if spec.isEntered then
1250 g_currentMission:onLeaveVehicle()
1251 g_currentMission.eventActivateObject = ""
1252 end
1253end

actionEventResetHeadTracking

Description
Definition
actionEventResetHeadTracking()
Code
1288function Enterable.actionEventResetHeadTracking(self, actionName, inputValue, callbackState, isAnalog)
1289 centerHeadTracking()
1290end

addToolCameras

Description
Add cameras from tool
Definition
addToolCameras(table cameras)
Arguments
tablecamerascameras to add
Code
723function Enterable:addToolCameras(cameras)
724 local spec = self.spec_enterable
725
726 for _,toolCamera in pairs(cameras) do
727 table.insert(spec.cameras, toolCamera)
728 end
729 spec.numCameras = #spec.cameras
730end

deleteVehicleCharacter

Description
Definition
deleteVehicleCharacter()
Code
867function Enterable:deleteVehicleCharacter()
868 local spec = self.spec_enterable
869 if spec.vehicleCharacter ~= nil then
870 spec.vehicleCharacter:delete()
871 end
872end

drawUIInfo

Description
Called on ui info draw, renders nicknames in multiplayer
Definition
drawUIInfo()
Code
937function Enterable:drawUIInfo(superFunc)
938 local spec = self.spec_enterable
939
940 superFunc(self)
941
942 if not spec.isEntered and self.isClient and self:getIsActive() and spec.isControlled and not g_gui:getIsGuiVisible() and not g_flightAndNoHUDKeysEnabled then
943 local x,y,z = getWorldTranslation(spec.nicknameRendering.node)
944 local x1,y1,z1 = getWorldTranslation(getCamera())
945 local distSq = MathUtil.vector3LengthSq(x-x1,y-y1,z-z1)
946 if distSq <= 100*100 then
947 x = x + spec.nicknameRendering.offset[1]
948 y = y + spec.nicknameRendering.offset[2]
949 z = z + spec.nicknameRendering.offset[3]
950
951 Utils.renderTextAtWorldPosition(x,y,z, self:getControllerName(), getCorrectTextSize(0.02), 0)
952 end
953 end
954end

enterVehicle

Description
Enter vehicle
Definition
enterVehicle(boolean isControlling, integer playerIndex, integer playerColorIndex)
Arguments
booleanisControllingis controlling vehicle
integerplayerIndexindex of player who enters the vehicle
integerplayerColorIndexindex of player color
Code
573function Enterable:enterVehicle(isControlling, playerStyle, farmId)
574 local spec = self.spec_enterable
575
576 self:raiseActive()
577
578 spec.isControlled = true
579 spec.isEntered = isControlling
580 spec.playerStyle = playerStyle
581 spec.canUseEnter = false
582 spec.controllerFarmId = farmId
583
584 g_currentMission.controlledVehicles[self] = self
585
586 if spec.forceSelectionOnEnter then
587 local rootAttacherVehicle = self:getRootVehicle()
588 if rootAttacherVehicle ~= self then
589 rootAttacherVehicle:setSelectedImplementByObject(self)
590 end
591 end
592
593 if spec.isEntered then
594 -- if head tracking is available we want to use the first indoor camera
595 if g_gameSettings:getValue("isHeadTrackingEnabled") and isHeadTrackingAvailable() then
596 for i,camera in pairs(spec.cameras) do
597 if camera.isInside then
598 spec.camIndex = i
599 break
600 end
601 end
602 end
603
604 if g_gameSettings:getValue("resetCamera") then
605 spec.camIndex = 1
606 end
607 self:setActiveCameraIndex(spec.camIndex)
608 end
609
610 if not self:getIsAIActive() then
611 local playerModel = g_playerModelManager:getPlayerModelByIndex(spec.playerStyle.selectedModelIndex)
612 self:setVehicleCharacter(playerModel.xmlFilename, spec.playerStyle)
613
614 if spec.enterAnimation ~= nil and self.playAnimation ~= nil then
615 self:playAnimation(spec.enterAnimation, 1, nil, true)
616 end
617 end
618
619 SpecializationUtil.raiseEvent(self, "onEnterVehicle", isControlling)
620
621 -- activate actionEvents
622 if self.isClient then
623 g_messageCenter:subscribe(MessageType.INPUT_BINDINGS_CHANGED, self.requestActionEventUpdate, self)
624 self:requestActionEventUpdate()
625 end
626
627 if self.isServer and not isControlling and g_currentMission.trafficSystem ~= nil and g_currentMission.trafficSystem.trafficSystemId ~= 0 then
628 addTrafficSystemPlayer(g_currentMission.trafficSystem.trafficSystemId, self.components[1].node)
629 end
630
631 self:activate()
632end

getActiveCamera

Description
Definition
getActiveCamera()
Code
1097function Enterable:getActiveCamera()
1098 return self.spec_enterable.activeCamera
1099end

getActiveFarm

Description
Definition
getActiveFarm()
Code
1139function Enterable:getActiveFarm(superFunc)
1140 local spec = self.spec_enterable
1141
1142 local farmId = spec.controllerFarmId
1143 if farmId ~= 0 then
1144 return farmId
1145 else
1146 return superFunc(self)
1147 end
1148end

getAllowCharacterVisibilityUpdate

Description
Definition
getAllowCharacterVisibilityUpdate()
Code
1109function Enterable:getAllowCharacterVisibilityUpdate()
1110 return true
1111end

getCanToggleAttach

Description
Definition
getCanToggleAttach()
Code
1130function Enterable:getCanToggleAttach(superFunc)
1131 if not self:getIsEntered() then
1132 return false
1133 end
1134 return superFunc(self)
1135end

getCanToggleSelectable

Description
Definition
getCanToggleSelectable()
Code
1121function Enterable:getCanToggleSelectable(superFunc)
1122 if self:getIsEntered() then
1123 return true
1124 end
1125 return superFunc(self)
1126end

getControllerName

Description
Definition
getControllerName()
Code
1091function Enterable:getControllerName()
1092 return self.spec_enterable.playerStyle.playerName
1093end

getCurrentPlayerStyle

Description
Definition
getCurrentPlayerStyle()
Code
793function Enterable:getCurrentPlayerStyle()
794 local spec = self.spec_enterable
795 if spec.vehicleCharacter ~= nil then
796 return spec.vehicleCharacter:getPlayerStyle()
797 end
798end

getDisableVehicleCharacterOnLeave

Description
Definition
getDisableVehicleCharacterOnLeave()
Code
1115function Enterable:getDisableVehicleCharacterOnLeave()
1116 return self.spec_enterable.disableCharacterOnLeave
1117end

getDistanceToNode

Description
Returns distance between given object and enterReferenceNode
Definition
getDistanceToNode(integer object)
Arguments
integerobjectid of object
Return Values
floatdistancedistance
Code
961function Enterable:getDistanceToNode(superFunc, node)
962 local spec = self.spec_enterable
963
964 local superDistance = superFunc(self, node)
965
966 if spec == nil or spec.enterReferenceNode == nil then
967 return superDistance
968 end
969
970 local px, py, pz = getWorldTranslation(node)
971 local vx, vy, vz = getWorldTranslation(spec.enterReferenceNode)
972 local distance = MathUtil.vector3Length(px-vx, py-vy, pz-vz)
973
974 if distance < spec.interactionRadius and distance < superDistance then
975 self.interactionFlag = Vehicle.INTERACTION_FLAG_ENTERABLE
976 return distance
977 end
978
979 return superDistance
980end

getExitNode

Description
Definition
getExitNode()
Code
768function Enterable:getExitNode()
769 local spec = self.spec_enterable
770 return spec.exitPoint
771end

getFormattedOperatingTime

Description
Definition
getFormattedOperatingTime()
Code
876function Enterable:getFormattedOperatingTime()
877 local minutes = self.operatingTime / (1000 * 60)
878 local hours = math.floor(minutes / 60)
879 minutes = math.floor((minutes - hours * 60) / 6)
880 local minutesString = string.format("%02d", minutes*10)
881
882 return tonumber(hours.."."..minutesString)
883end

getInteractionHelp

Description
Returns interaction help text
Definition
getInteractionHelp()
Return Values
stringtexttext
Code
985function Enterable:getInteractionHelp(superFunc)
986 if self.interactionFlag == Vehicle.INTERACTION_FLAG_ENTERABLE then
987 return g_i18n:getText("action_enter")
988 else
989 return superFunc(self)
990 end
991end

getIsActive

Description
Definition
getIsActive()
Code
887function Enterable:getIsActive(superFunc)
888 local spec = self.spec_enterable
889 if spec.isEntered or spec.isControlled then
890 return true
891 else
892 return superFunc(self)
893 end
894end

getIsActiveForInput

Description
Definition
getIsActiveForInput()
Code
898function Enterable:getIsActiveForInput(superFunc, ignoreSelection, activeForAI)
899 if not superFunc(self, ignoreSelection, activeForAI) then
900 return false
901 end
902
903 if g_currentMission.isPlayerFrozen then
904 return false
905 end
906
907 local spec = self.spec_enterable
908 if not spec.isEntered or not spec.isControlled then
909 -- if the vehicle we check if not entered we check if there is another enterable vehicle attached
910 -- if yes we check if that vehicle is entered since only one vehicle in the "vehicle chain" has to be entered
911 local noOtherEnterableIsEntered = true
912
913 local vehicles = {}
914 self:getRootVehicle():getChildVehicles(vehicles)
915
916 for _, vehicle in ipairs(vehicles) do
917 local vehicleSpec = vehicle.spec_enterable
918 if vehicleSpec ~= nil then
919 if vehicle ~= self then
920 if vehicleSpec.isEntered or vehicleSpec.isControlled then
921 noOtherEnterableIsEntered = false
922 end
923 end
924 end
925 end
926
927 if noOtherEnterableIsEntered then
928 return false
929 end
930 end
931
932 return true
933end

getIsAdditionalCharacterActive

Description
Definition
getIsAdditionalCharacterActive()
Code
413function Enterable:getIsAdditionalCharacterActive()
414 return false
415end

getIsControlled

Description
Definition
getIsControlled()
Code
1085function Enterable:getIsControlled()
1086 return self.spec_enterable.isControlled
1087end

getIsDashboardGroupActive

Description
Definition
getIsDashboardGroupActive()
Code
1164function Enterable:getIsDashboardGroupActive(superFunc, group)
1165 if group.isEntered ~= nil then
1166 if group.isEntered ~= self:getIsEntered() then
1167 return false
1168 end
1169 end
1170
1171 return superFunc(self, group)
1172end

getIsEnterable

Description
Get whether current player can enter this vehicle Only works when isClient
Definition
getIsEnterable()
Code
1072function Enterable:getIsEnterable()
1073 local spec = self.spec_enterable
1074 return not spec.isBroken and not spec.isControlled and g_currentMission.accessHandler:canPlayerAccess(self)
1075end

getIsEntered

Description
Definition
getIsEntered()
Code
1079function Enterable:getIsEntered()
1080 return self.spec_enterable.isEntered
1081end

getIsInUse

Description
Definition
getIsInUse()
Code
1188function Enterable:getIsInUse(superFunc, connection)
1189 local spec = self.spec_enterable
1190 if spec.isControlled and self:getOwner() ~= connection then
1191 return true
1192 end
1193
1194 return superFunc(self, connection)
1195end

getIsTabbable

Description
Definition
getIsTabbable()
Code
1059function Enterable:getIsTabbable()
1060 return self.spec_enterable.isTabbable
1061end

getPlayerColorIndex

Description
Definition
getPlayerColorIndex()
Code
781function Enterable:getPlayerColorIndex()
782 return self.spec_enterable.playerStyle.selectedColorIndex
783end

getPlayerModelIndex

Description
Definition
getPlayerModelIndex()
Code
775function Enterable:getPlayerModelIndex()
776 return self.spec_enterable.playerStyle.selectedModelIndex
777end

getUserPlayerStyle

Description
Definition
getUserPlayerStyle()
Code
787function Enterable:getUserPlayerStyle()
788 return self.spec_enterable.playerStyle
789end

getVehicleCharacter

Description
Definition
getVehicleCharacter()
Code
1103function Enterable:getVehicleCharacter()
1104 return self.spec_enterable.vehicleCharacter
1105end

interact

Description
Interact
Definition
interact()
Code
995function Enterable:interact(superFunc)
996 if self.interactionFlag == Vehicle.INTERACTION_FLAG_ENTERABLE then
997 g_currentMission:requestToEnterVehicle(self)
998 else
999 superFunc(self)
1000 end
1001end

leaveVehicle

Description
Leave vehicle
Definition
leaveVehicle()
Code
636function Enterable:leaveVehicle()
637 local spec = self.spec_enterable
638
639 g_currentMission:removePauseListeners(self)
640
641 if spec.activeCamera ~= nil and spec.isEntered then
642 spec.activeCamera:onDeactivate()
643 g_soundManager:setIsIndoor(false)
644
645 g_depthOfFieldManager:reset()
646 end
647
648 if self.spec_rideable ~= nil then
649 -- To be called before "spec.vehicleCharacter:delete()"
650 self:setEquipmentVisibility(false)
651 self:unlinkReins()
652 end
653
654 spec.isControlled = false
655 spec.isEntered = false
656 spec.playerIndex = 0
657 spec.playerColorIndex = 0
658 spec.canUseEnter = true
659 spec.controllerFarmId = 0
660
661 g_currentMission.controlledVehicles[self] = nil
662 g_currentMission:setLastInteractionTime(200)
663
664 if spec.vehicleCharacter ~= nil and self:getDisableVehicleCharacterOnLeave() then
665 spec.vehicleCharacter:delete()
666 end
667
668 if spec.enterAnimation ~= nil and self.playAnimation ~= nil then
669 self:playAnimation(spec.enterAnimation, -1, nil, true)
670 end
671
672 self:setMirrorVisible(false)
673
674 SpecializationUtil.raiseEvent(self, "onLeaveVehicle")
675
676 -- deactivate actionEvents
677 if self.isClient then
678 g_messageCenter:unsubscribe(MessageType.INPUT_BINDINGS_CHANGED, self)
679 self:requestActionEventUpdate()
680 end
681
682 if self.isServer and not spec.isEntered and g_currentMission.trafficSystem ~= nil and g_currentMission.trafficSystem.trafficSystemId ~= 0 then
683 removeTrafficSystemPlayer(g_currentMission.trafficSystem.trafficSystemId, self.components[1].node)
684 end
685
686 if self:getDeactivateOnLeave() then
687 self:deactivate()
688 end
689end

loadAdditionalCharacterFromXML

Description
Definition
loadAdditionalCharacterFromXML()
Code
398function Enterable:loadAdditionalCharacterFromXML(xmlFile)
399 local spec = self.spec_enterable
400
401 spec.additionalCharacterNode = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.enterable.additionalCharacter#node"), self.i3dMappings)
402 spec.additionalCharacterTargets = {}
403 IKUtil.loadIKChainTargets(self.xmlFile, "vehicle.enterable.additionalCharacter", self.components, spec.additionalCharacterTargets, self.i3dMappings)
404 spec.additionalCharacterActive = false
405 if spec.vehicleCharacter ~= nil then
406 spec.defaultCharacterNode = spec.vehicleCharacter.characterNode
407 spec.defaultCharacterTargets = spec.vehicleCharacter:getIKChainTargets()
408 end
409end

loadCamerasFromXML

Description
Definition
loadCamerasFromXML()
Code
371function Enterable:loadCamerasFromXML(xmlFile)
372 local spec = self.spec_enterable
373
374 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.cameras.camera(0)#index", "vehicle.enterable.cameras.camera(0)#node") -- FS17
375 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.cameras.camera(0).raycastNode(0)#index", "vehicle.enterable.cameras.camera(0).raycastNode(0)#node") -- FS17
376
377 spec.cameras = {}
378 local i = 0
379 while true do
380 local cameraKey = string.format("vehicle.enterable.cameras.camera(%d)", i)
381 if not hasXMLProperty(xmlFile, cameraKey) then
382 break
383 end
384
385 local camera = VehicleCamera:new(self)
386 if camera:loadFromXML(xmlFile, cameraKey) then
387 table.insert(spec.cameras, camera)
388 end
389 i = i + 1
390 end
391 spec.numCameras = table.getn(spec.cameras)
392
393 spec.camIndex = 1
394end

loadCharacterTargetNodeModifier

Description
Definition
loadCharacterTargetNodeModifier()
Code
419function Enterable:loadCharacterTargetNodeModifier(entry, xmlFile, xmlKey)
420 XMLUtil.checkDeprecatedXMLElements(xmlFile, self.configFileName, xmlKey .. "#index", xmlKey .. "#node") --FS17 to FS19
421
422 entry.node = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, xmlKey .. "#node"), self.i3dMappings)
423 if entry.node ~= nil then
424 entry.parent = getParent(entry.node)
425 entry.translationOffset = {getTranslation(entry.node)}
426 entry.rotationOffset = {getRotation(entry.node)}
427 entry.poseId = getXMLString(xmlFile, xmlKey .. "#poseId")
428
429 entry.states = {}
430
431 local j = 0
432 while true do
433 local stateKey = string.format("%s.state(%d)", xmlKey, j)
434 if not hasXMLProperty(xmlFile, stateKey) then
435 break
436 end
437
438 XMLUtil.checkDeprecatedXMLElements(xmlFile, self.configFileName, stateKey .. "#index", stateKey .. "#node") --FS17 to FS19
439
440 local node = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, stateKey .. "#node"), self.i3dMappings)
441 if node ~= nil then
442 local state = {}
443 state.node = node
444 state.referenceNode = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, stateKey .. "#referenceNode"), self.i3dMappings)
445 state.directionReferenceNode = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, stateKey .. "#directionReferenceNode"), self.i3dMappings)
446 state.poseId = getXMLString(xmlFile, stateKey .. "#poseId")
447
448 if state.referenceNode ~= nil then
449 state.defaultRotation = {getRotation(state.referenceNode)}
450 state.defaultTranslation = {getTranslation(state.referenceNode)}
451
452 table.insert(entry.states, state)
453 end
454 else
455 g_logManager:xmlWarning(self.configFileName, "Missing node for state '%s'", stateKey)
456 end
457
458 j = j + 1
459 end
460
461 entry.transitionTime = Utils.getNoNil(getXMLFloat(self.xmlFile, xmlKey .. "#transitionTime"), 0.1) * 1000
462 entry.transitionAlpha = 1.0
463
464 entry.transitionIdleDelay = Utils.getNoNil(getXMLFloat(self.xmlFile, xmlKey .. "#transitionIdleDelay"), 0.5) * 1000
465 entry.transitionIdleTime = 0
466
467 return true
468 end
469
470 return false
471end

loadDashboardGroupFromXML

Description
Definition
loadDashboardGroupFromXML()
Code
1152function Enterable:loadDashboardGroupFromXML(superFunc, xmlFile, key, group)
1153 if not superFunc(self, xmlFile, key, group) then
1154 return false
1155 end
1156
1157 group.isEntered = getXMLBool(xmlFile, key .. "#isEntered")
1158
1159 return true
1160end

mountDynamic

Description
Definition
mountDynamic()
Code
1176function Enterable:mountDynamic(superFunc, object, objectActorId, jointNode, mountType, forceAcceleration)
1177 local spec = self.spec_enterable
1178
1179 if spec.isControlled then
1180 return false
1181 end
1182
1183 return superFunc(self, object, objectActorId, jointNode, mountType, forceAcceleration)
1184end

onDelete

Description
Called on deleting
Definition
onDelete()
Code
238function Enterable:onDelete()
239 local spec = self.spec_enterable
240
241 if spec.vehicleCharacter ~= nil then
242 spec.vehicleCharacter:delete()
243 end
244 for _, camera in ipairs(spec.cameras) do
245 camera:delete()
246 end
247
248 g_currentMission:removeEnterableVehicle(self)
249 g_currentMission:removeInteractiveVehicle(self)
250end

onLoad

Description
Definition
onLoad()
Code
104function Enterable:onLoad(savegame)
105
106 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.mirrors.mirror(0)#index", "vehicle.enterable.mirrors.mirror(0)#node") --FS17 to FS19
107 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.enterReferenceNode", "vehicle.enterable.enterReferenceNode") --FS17 to FS19
108 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.enterReferenceNode#index", "vehicle.enterable.enterReferenceNode#node") --FS17 to FS19
109 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.enterable.enterReferenceNode#index", "vehicle.enterable.enterReferenceNode#node") --FS17 to FS19
110 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.exitPoint", "vehicle.enterable.exitPoint") --FS17 to FS19
111 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.exitPoint#index", "vehicle.enterable.exitPoint#node") --FS17 to FS19
112 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.enterable.exitPoint#index", "vehicle.enterable.exitPoint#node") --FS17 to FS19
113 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.characterNode", "vehicle.enterable.characterNode") --FS17 to FS19
114 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.characterNode#index", "vehicle.enterable.characterNode#node") --FS17 to FS19
115 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.enterable.characterNode#index", "vehicle.enterable.characterNode#node") --FS17 to FS19
116 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.nicknameRenderNode", "vehicle.enterable.nicknameRenderNode") --FS17 to FS19
117 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.enterAnimation", "vehicle.enterable.enterAnimation") --FS17 to FS19
118 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.cameras.camera1", "vehicle.enterable.cameras.camera") --FS17 to FS19
119 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.enterable.cameras.camera1", "vehicle.enterable.cameras.camera") --FS17 to FS19
120 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.indoorHud.time", "vehicle.enterable.dashboards.dashboard with valueType 'time'") --FS17 to FS19
121 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.indoorHud.operatingTime", "vehicle.enterable.dashboards.dashboard with valueType 'operatingTime'") --FS17 to FS19
122
123 local spec = self.spec_enterable
124
125 spec.isTabbable = Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.enterable#isTabbable"), true)
126 spec.isEntered = false
127 spec.isControlled = false
128 spec.playerStyle = nil
129 spec.canUseEnter = true
130 spec.controllerFarmId = 0
131
132 spec.disableCharacterOnLeave = true
133
134 spec.forceSelectionOnEnter = Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.enterable.forceSelectionOnEnter"), false)
135
136 spec.enterReferenceNode = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.enterable.enterReferenceNode#node"), self.i3dMappings)
137 spec.exitPoint = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.enterable.exitPoint#node"), self.i3dMappings)
138
139 spec.interactionRadius = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.enterable.enterReferenceNode#interactionRadius"), 6.0)
140
141 spec.vehicleCharacter = VehicleCharacter:new(self)
142 if spec.vehicleCharacter ~= nil and not spec.vehicleCharacter:load(self.xmlFile, "vehicle.enterable.characterNode", self.i3dMappings) then
143 spec.vehicleCharacter = nil
144 end
145
146 self:loadAdditionalCharacterFromXML(self.xmlFile)
147
148 spec.nicknameRendering = {}
149 spec.nicknameRendering.node = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.enterable.nicknameRenderNode#index"), self.i3dMappings)
150 spec.nicknameRendering.offset = StringUtil.getVectorNFromString(getXMLString(self.xmlFile, "vehicle.enterable.nicknameRenderNode#offset"), 3)
151 if spec.nicknameRendering.node == nil then
152 if spec.vehicleCharacter ~= nil and spec.vehicleCharacter.characterDistanceRefNode ~= nil then
153 spec.nicknameRendering.node = spec.vehicleCharacter.characterDistanceRefNode
154 if spec.nicknameRendering.offset == nil then
155 spec.nicknameRendering.offset = {0, 1.5, 0}
156 end
157 else
158 spec.nicknameRendering.node = self.components[1].node
159 end
160 end
161 if spec.nicknameRendering.offset == nil then
162 spec.nicknameRendering.offset = {0, 4, 0}
163 end
164
165 spec.enterAnimation = getXMLString(self.xmlFile, "vehicle.enterable.enterAnimation#name")
166 if spec.enterAnimation ~= nil and not self:getAnimationExists(spec.enterAnimation) then
167 g_logManager:xmlWarning(self.configFileName, "Unable to find enter animation '%s'", spec.enterAnimation)
168 end
169
170 self:loadCamerasFromXML(self.xmlFile)
171
172 if spec.numCameras == 0 then
173 g_logManager:xmlError(self.configFileName, "No cameras defined!")
174 self:setLoadingState(BaseMission.VEHICLE_LOAD_ERROR)
175 return
176 end
177
178 spec.characterTargetNodeModifiers = {}
179 local i = 0
180 while true do
181 local key = string.format("vehicle.enterable.characterTargetNodeModifier(%d)", i)
182 if not hasXMLProperty(self.xmlFile, key) then
183 break
184 end
185
186 local modifier = {}
187 if self:loadCharacterTargetNodeModifier(modifier, self.xmlFile, key) then
188 table.insert(spec.characterTargetNodeModifiers, modifier)
189 end
190 i = i + 1
191 end
192
193 spec.mirrors = {}
194 local useMirrors = g_gameSettings:getValue("maxNumMirrors") > 0
195 i = 0
196 while true do
197 local key = string.format("vehicle.enterable.mirrors.mirror(%d)", i)
198 if not hasXMLProperty(self.xmlFile, key) then
199 break
200 end
201
202 local node = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, key.."#node"), self.i3dMappings)
203 if node ~= nil then
204 local prio = Utils.getNoNil(getXMLInt(self.xmlFile, key.."#prio"), 2)
205 setReflectionMapObjectMasks(node, 32896, 2147483648, true) --0x8080, 0x80000000
206 if getObjectMask(node) == 0 then
207 -- Mirrors should not be visible in other mirrors
208 setObjectMask(node, 16711807) -- 0x00FF007F
209 end
210
211 if useMirrors then
212 table.insert(spec.mirrors, {node=node, prio=prio, cosAngle=1})
213 else
214 setVisibility(node, false)
215 end
216 end
217 i = i + 1
218 end
219
220 self:setMirrorVisible(spec.cameras[spec.camIndex].useMirror)
221
222 if self.loadDashboardsFromXML ~= nil then
223 self:loadDashboardsFromXML(self.xmlFile, "vehicle.enterable.dashboards", {valueTypeToLoad = "time",
224 valueObject = g_currentMission.environment,
225 valueFunc = "getEnvironmentTime"})
226
227 self:loadDashboardsFromXML(self.xmlFile, "vehicle.enterable.dashboards", {valueTypeToLoad = "operatingTime",
228 valueObject = self,
229 valueFunc = "getFormattedOperatingTime"})
230 end
231
232 g_currentMission:addInteractiveVehicle(self)
233 g_currentMission:addEnterableVehicle(self)
234end

onPostUpdate

Description
Called on postUpdate
Definition
onPostUpdate(float dt, boolean isActiveForInput, boolean isSelected)
Arguments
floatdttime since last call in ms
booleanisActiveForInputtrue if vehicle is active for input
booleanisSelectedtrue if vehicle is selected
Code
337function Enterable:onPostUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
338 local spec = self.spec_enterable
339
340 if self.isClient then
341 if spec.isEntered and spec.vehicleCharacter ~= nil then
342 if spec.vehicleCharacter.characterSpineNode ~= nil and spec.vehicleCharacter.characterSpineSpeedDepended then
343 spec.vehicleCharacter:setSpineDirty(self.lastSpeedAcceleration)
344 end
345 end
346
347 if self.firstTimeRun then
348 if self:getIsEntered() then
349 spec.activeCamera:update(dt)
350 end
351
352 -- update character visiblity
353 if self:getAllowCharacterVisibilityUpdate() then
354 if spec.vehicleCharacter ~= nil then
355 spec.vehicleCharacter:updateVisibility()
356 end
357 end
358 end
359
360 if self:getIsControlled() then
361 -- do mirror checks
362 if spec.activeCamera ~= nil and spec.activeCamera.useMirror then
363 self:setMirrorVisible(true)
364 end
365 end
366 end
367end

onPreLoad

Description
Definition
onPreLoad()
Code
98function Enterable:onPreLoad(savegame)
99 Vehicle.registerInteractionFlag("Enterable")
100end

onReadStream

Description
Called on client side on join
Definition
onReadStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
256function Enterable:onReadStream(streamId, connection)
257 local isControlled = streamReadBool(streamId)
258 if isControlled then
259 local playerStyle = PlayerStyle:new()
260 playerStyle:readStream(streamId, connection)
261 local farmId = streamReadUIntN(streamId, FarmManager.FARM_ID_SEND_NUM_BITS)
262 self:enterVehicle(false, playerStyle, farmId)
263 end
264end

onRegisterActionEvents

Description
Definition
onRegisterActionEvents()
Code
1199function Enterable:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection)
1200 if self:getIsEntered() then
1201 local spec = self.spec_enterable
1202 self:clearActionEventsTable(spec.actionEvents)
1203
1204 if self:getIsActiveForInput(true, true) then
1205 local actionEventId
1206 _, actionEventId = self:addActionEvent(spec.actionEvents, InputAction.ENTER, self, Enterable.actionEventLeave, false, true, false, true, nil)
1207 g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_VERY_HIGH)
1208 g_inputBinding:setActionEventTextVisibility(actionEventId, false)
1209
1210 _, actionEventId = self:addActionEvent(spec.actionEvents, InputAction.ACTIVATE_OBJECT, self, Enterable.actionEventActivateObject, false, true, false, false, nil)
1211 g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_VERY_HIGH)
1212 g_inputBinding:setActionEventTextVisibility(actionEventId, false)
1213 g_currentMission.eventActivateObject = actionEventId
1214
1215 if spec.numCameras > 1 then
1216 _, actionEventId = self:addActionEvent(spec.actionEvents, InputAction.CAMERA_SWITCH, self, Enterable.actionEventCameraSwitch, false, true, false, true, nil)
1217 g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_LOW)
1218 g_inputBinding:setActionEventTextVisibility(actionEventId, true)
1219 end
1220
1221 _, actionEventId = self:addActionEvent(spec.actionEvents, InputAction.CAMERA_ZOOM_IN, self, Enterable.actionEventCameraZoomIn, false, true, true, true, nil)
1222 g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_LOW)
1223 g_inputBinding:setActionEventTextVisibility(actionEventId, false)
1224
1225 _, actionEventId = self:addActionEvent(spec.actionEvents, InputAction.CAMERA_ZOOM_OUT, self, Enterable.actionEventCameraZoomOut, false, true, true, true, nil)
1226 g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_LOW)
1227 g_inputBinding:setActionEventTextVisibility(actionEventId, false)
1228
1229 _, actionEventId = self:addActionEvent(spec.actionEvents, InputAction.RESET_HEAD_TRACKING, self, Enterable.actionEventResetHeadTracking, false, true, false, true, nil)
1230 g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_VERY_LOW)
1231 g_inputBinding:setActionEventTextVisibility(actionEventId, false)
1232 end
1233 end
1234end

onSetBroken

Description
Definition
onSetBroken()
Code
1238function Enterable:onSetBroken()
1239 local spec = self.spec_enterable
1240 if spec.isEntered then
1241 g_currentMission:onLeaveVehicle()
1242 end
1243end

onUpdate

Description
Called on update
Definition
onUpdate(float dt, boolean isActiveForInput, boolean isSelected)
Arguments
floatdttime since last call in ms
booleanisActiveForInputtrue if vehicle is active for input
booleanisSelectedtrue if vehicle is selected
Code
294function Enterable:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
295 local spec = self.spec_enterable
296 for _,modifier in ipairs(spec.characterTargetNodeModifiers) do
297 self:updateCharacterTargetNodeModifier(dt, modifier)
298 end
299
300 if self:getIsControlled() then
301 if self.isClient then
302 if spec.vehicleCharacter ~= nil and spec.vehicleCharacter.isCharacterLoaded then
303 spec.vehicleCharacter:update(dt)
304 end
305
306 if self:getIsAdditionalCharacterActive() ~= spec.additionalCharacterActive then
307 spec.additionalCharacterActive = not spec.additionalCharacterActive
308
309 local character = self:getVehicleCharacter()
310 if character ~= nil then
311 local node = spec.defaultCharacterNode
312 local targets = spec.defaultCharacterTargets
313 if spec.additionalCharacterActive then
314 targets = spec.additionalCharacterTargets
315 node =spec.additionalCharacterNode
316 end
317
318 character:setIKChainTargets(targets)
319
320 character.characterNode = node
321 character.characterDistanceRefNode = node
322 link(node, character.skeletonThirdPerson)
323 character.visualInformation:linkProtectiveWear(node)
324 end
325 end
326 end
327
328 self:getRootVehicle():raiseActive()
329 end
330end

onWriteStream

Description
Called on server side on join
Definition
onWriteStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
270function Enterable:onWriteStream(streamId, connection)
271 local spec = self.spec_enterable
272 if streamWriteBool(streamId, spec.isControlled) then
273 spec.playerStyle:writeStream(streamId, connection)
274 streamWriteUIntN(streamId, spec.controllerFarmId, FarmManager.FARM_ID_SEND_NUM_BITS)
275 end
276end

prerequisitesPresent

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

registerEventListeners

Description
Definition
registerEventListeners()
Code
84function Enterable.registerEventListeners(vehicleType)
85 SpecializationUtil.registerEventListener(vehicleType, "onPreLoad", Enterable)
86 SpecializationUtil.registerEventListener(vehicleType, "onLoad", Enterable)
87 SpecializationUtil.registerEventListener(vehicleType, "onDelete", Enterable)
88 SpecializationUtil.registerEventListener(vehicleType, "onReadStream", Enterable)
89 SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", Enterable)
90 SpecializationUtil.registerEventListener(vehicleType, "onUpdate", Enterable)
91 SpecializationUtil.registerEventListener(vehicleType, "onPostUpdate", Enterable)
92 SpecializationUtil.registerEventListener(vehicleType, "onRegisterActionEvents", Enterable)
93 SpecializationUtil.registerEventListener(vehicleType, "onSetBroken", Enterable)
94end

registerEvents

Description
Definition
registerEvents()
Code
21function Enterable.registerEvents(vehicleType)
22 SpecializationUtil.registerEvent(vehicleType, "onEnterVehicle")
23 SpecializationUtil.registerEvent(vehicleType, "onLeaveVehicle")
24 SpecializationUtil.registerEvent(vehicleType, "onCameraChanged")
25 SpecializationUtil.registerEvent(vehicleType, "onVehicleCharacterChanged")
26end

registerFunctions

Description
Definition
registerFunctions()
Code
30function Enterable.registerFunctions(vehicleType)
31 SpecializationUtil.registerFunction(vehicleType, "enterVehicle", Enterable.enterVehicle)
32 SpecializationUtil.registerFunction(vehicleType, "leaveVehicle", Enterable.leaveVehicle)
33 SpecializationUtil.registerFunction(vehicleType, "setActiveCameraIndex", Enterable.setActiveCameraIndex)
34 SpecializationUtil.registerFunction(vehicleType, "addToolCameras", Enterable.addToolCameras)
35 SpecializationUtil.registerFunction(vehicleType, "removeToolCameras", Enterable.removeToolCameras)
36 SpecializationUtil.registerFunction(vehicleType, "getExitNode", Enterable.getExitNode)
37 SpecializationUtil.registerFunction(vehicleType, "getPlayerModelIndex", Enterable.getPlayerModelIndex)
38 SpecializationUtil.registerFunction(vehicleType, "getPlayerColorIndex", Enterable.getPlayerColorIndex)
39 SpecializationUtil.registerFunction(vehicleType, "getUserPlayerStyle", Enterable.getUserPlayerStyle)
40 SpecializationUtil.registerFunction(vehicleType, "getCurrentPlayerStyle", Enterable.getCurrentPlayerStyle)
41 SpecializationUtil.registerFunction(vehicleType, "setVehicleCharacter", Enterable.setVehicleCharacter)
42 SpecializationUtil.registerFunction(vehicleType, "setRandomVehicleCharacter", Enterable.setRandomVehicleCharacter)
43 SpecializationUtil.registerFunction(vehicleType, "restoreVehicleCharacter", Enterable.restoreVehicleCharacter)
44 SpecializationUtil.registerFunction(vehicleType, "deleteVehicleCharacter", Enterable.deleteVehicleCharacter)
45 SpecializationUtil.registerFunction(vehicleType, "getFormattedOperatingTime", Enterable.getFormattedOperatingTime)
46 SpecializationUtil.registerFunction(vehicleType, "loadCharacterTargetNodeModifier", Enterable.loadCharacterTargetNodeModifier)
47 SpecializationUtil.registerFunction(vehicleType, "updateCharacterTargetNodeModifier", Enterable.updateCharacterTargetNodeModifier)
48 SpecializationUtil.registerFunction(vehicleType, "setMirrorVisible", Enterable.setMirrorVisible)
49 SpecializationUtil.registerFunction(vehicleType, "getIsTabbable", Enterable.getIsTabbable)
50 SpecializationUtil.registerFunction(vehicleType, "setIsTabbable", Enterable.setIsTabbable)
51 SpecializationUtil.registerFunction(vehicleType, "getIsEnterable", Enterable.getIsEnterable)
52 SpecializationUtil.registerFunction(vehicleType, "getIsEntered", Enterable.getIsEntered)
53 SpecializationUtil.registerFunction(vehicleType, "getIsControlled", Enterable.getIsControlled)
54 SpecializationUtil.registerFunction(vehicleType, "getControllerName", Enterable.getControllerName)
55 SpecializationUtil.registerFunction(vehicleType, "getActiveCamera", Enterable.getActiveCamera)
56 SpecializationUtil.registerFunction(vehicleType, "getVehicleCharacter", Enterable.getVehicleCharacter)
57 SpecializationUtil.registerFunction(vehicleType, "getAllowCharacterVisibilityUpdate", Enterable.getAllowCharacterVisibilityUpdate)
58 SpecializationUtil.registerFunction(vehicleType, "getDisableVehicleCharacterOnLeave", Enterable.getDisableVehicleCharacterOnLeave)
59 SpecializationUtil.registerFunction(vehicleType, "loadCamerasFromXML", Enterable.loadCamerasFromXML)
60 SpecializationUtil.registerFunction(vehicleType, "loadAdditionalCharacterFromXML", Enterable.loadAdditionalCharacterFromXML)
61 SpecializationUtil.registerFunction(vehicleType, "getIsAdditionalCharacterActive", Enterable.getIsAdditionalCharacterActive)
62end

registerOverwrittenFunctions

Description
Definition
registerOverwrittenFunctions()
Code
66function Enterable.registerOverwrittenFunctions(vehicleType)
67 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsActive", Enterable.getIsActive)
68 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsActiveForInput", Enterable.getIsActiveForInput)
69 SpecializationUtil.registerOverwrittenFunction(vehicleType, "drawUIInfo", Enterable.drawUIInfo)
70 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getDistanceToNode", Enterable.getDistanceToNode)
71 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getInteractionHelp", Enterable.getInteractionHelp)
72 SpecializationUtil.registerOverwrittenFunction(vehicleType, "interact", Enterable.interact)
73 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getCanToggleSelectable", Enterable.getCanToggleSelectable)
74 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getCanToggleAttach", Enterable.getCanToggleAttach)
75 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getActiveFarm", Enterable.getActiveFarm)
76 SpecializationUtil.registerOverwrittenFunction(vehicleType, "loadDashboardGroupFromXML", Enterable.loadDashboardGroupFromXML)
77 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsDashboardGroupActive", Enterable.getIsDashboardGroupActive)
78 SpecializationUtil.registerOverwrittenFunction(vehicleType, "mountDynamic", Enterable.mountDynamic)
79 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsInUse", Enterable.getIsInUse)
80end

removeToolCameras

Description
Remove cameras from tool
Definition
removeToolCameras(table cameras)
Arguments
tablecamerascameras to remove
Code
735function Enterable:removeToolCameras(cameras)
736 local spec = self.spec_enterable
737
738 local isToolCameraActive = false
739
740 for j = #spec.cameras, 1, -1 do
741 local camera = spec.cameras[j]
742 for _,toolCamera in pairs(cameras) do
743 if toolCamera == camera then
744 table.remove(spec.cameras, j)
745 if j == spec.camIndex then
746 isToolCameraActive = true
747 end
748 break
749 end
750 end
751 end
752
753 spec.numCameras = #spec.cameras
754
755 -- only reset camera if current camera was a tool camera which is not available anymore
756 if isToolCameraActive then
757 if spec.activeCamera ~= nil then
758 spec.activeCamera:onDeactivate()
759 end
760
761 spec.camIndex = 1
762 self:setActiveCameraIndex(spec.camIndex)
763 end
764end

restoreVehicleCharacter

Description
Definition
restoreVehicleCharacter()
Code
853function Enterable:restoreVehicleCharacter()
854 local spec = self.spec_enterable
855 if spec.vehicleCharacter ~= nil then
856 if self:getIsControlled() then
857 local playerModel = g_playerModelManager:getPlayerModelByIndex(self:getPlayerModelIndex())
858 self:setVehicleCharacter(playerModel.xmlFilename, self:getUserPlayerStyle())
859 else
860 self:deleteVehicleCharacter()
861 end
862 end
863end

saveStatsToXMLFile

Description
Returns string with name of controller for game stats xml
Definition
saveStatsToXMLFile()
Return Values
stringstatesAttributesstates attributes
Code
281function Enterable:saveStatsToXMLFile(xmlFile, key)
282 local spec = self.spec_enterable
283 if spec.isControlled and spec.playerStyle ~= nil and spec.playerStyle.playerName ~= nil then
284 setXMLString(xmlFile, key.."#controller", HTMLUtil.encodeToHTML(tostring(spec.playerStyle.playerName)))
285 end
286 return nil
287end

setActiveCameraIndex

Description
Change active camera index
Definition
setActiveCameraIndex(integer index)
Arguments
integerindexindex of camera to set
Code
694function Enterable:setActiveCameraIndex(index)
695 local spec = self.spec_enterable
696
697 if spec.activeCamera ~= nil then
698 spec.activeCamera:onDeactivate()
699 end
700 spec.camIndex = index
701 if spec.camIndex > spec.numCameras then
702 spec.camIndex = 1
703 end
704 local activeCamera = spec.cameras[spec.camIndex]
705 spec.activeCamera = activeCamera
706 activeCamera:onActivate()
707
708 g_soundManager:setIsIndoor(not activeCamera.useOutdoorSounds)
709 self:setMirrorVisible(activeCamera.useMirror)
710
711 if activeCamera.isInside then
712 g_depthOfFieldManager:setManipulatedParams(nil, 0.6, nil, nil, nil)
713 else
714 g_depthOfFieldManager:reset()
715 end
716
717 SpecializationUtil.raiseEvent(self, "onCameraChanged", activeCamera, spec.camIndex)
718end

setIsTabbable

Description
Definition
setIsTabbable()
Code
1065function Enterable:setIsTabbable(isTabbable)
1066 self.spec_enterable.isTabbable = isTabbable
1067end

setMirrorVisible

Description
Definition
setMirrorVisible()
Code
1005function Enterable:setMirrorVisible(visible)
1006 local spec = self.spec_enterable
1007
1008 if next(spec.mirrors) == nil then
1009 return
1010 end
1011
1012 if visible then
1013 local numVisibleMirrors = 0
1014 for _, mirror in pairs(spec.mirrors) do
1015 -- only use mirrors which are visible on screen
1016 if getIsInCameraFrustum(mirror.node, spec.activeCamera.cameraNode, g_presentedScreenAspectRatio) then
1017 -- calculate angle between mirror and camera
1018 --local dirX, dirY, dirZ = worldToLocal(spec.activeCamera.cameraNode, getWorldTranslation(mirror.node))
1019 local dirX, dirY, dirZ = localToLocal(spec.activeCamera.cameraNode, mirror.node, 0,0,0)
1020
1021 dirY = dirY * g_screenAspectRatio
1022 local length = MathUtil.vector3Length(dirX, dirY, dirZ)
1023 mirror.cosAngle = -dirZ / length
1024 else
1025 mirror.cosAngle = math.huge
1026 end
1027 end
1028
1029 -- sort mirrors based on prio and angle
1030 table.sort(spec.mirrors,
1031 function(mirror1, mirror2)
1032 if mirror1.prio == mirror2.prio then
1033 -- the bigger cosAngle, the smaller the angle to the z-axis
1034 return mirror1.cosAngle > mirror2.cosAngle
1035 else
1036 return mirror1.prio < mirror2.prio
1037 end
1038 end)
1039
1040 local maxNumMirrors = g_gameSettings:getValue("maxNumMirrors")
1041 -- show first mirrors within the limit
1042 for _, mirror in ipairs(spec.mirrors) do
1043 if mirror.cosAngle ~= math.huge and numVisibleMirrors < maxNumMirrors then
1044 setVisibility(mirror.node, true)
1045 numVisibleMirrors = numVisibleMirrors + 1
1046 else
1047 setVisibility(mirror.node, false)
1048 end
1049 end
1050 else
1051 for _, mirror in pairs(spec.mirrors) do
1052 setVisibility(mirror.node, false)
1053 end
1054 end
1055end

setRandomVehicleCharacter

Description
Definition
setRandomVehicleCharacter()
Code
818function Enterable:setRandomVehicleCharacter()
819 local spec = self.spec_enterable
820 if spec.vehicleCharacter ~= nil then
821 local aiPlayerModelIndex = math.random(1, g_playerModelManager:getNumOfPlayerModels())
822 local playerModel = g_playerModelManager:getPlayerModelByIndex(aiPlayerModelIndex)
823
824 self:setVehicleCharacter(playerModel.xmlFilename, PlayerStyle:new())
825
826 -- get new player style since it is duplicated
827 local aiStyle = self:getCurrentPlayerStyle()
828 local oldStyle = self:getUserPlayerStyle()
829
830 -- get random body that is not equal with the current one if the same model is selected
831 local numOfBodys = #aiStyle.bodies
832 local aiBodyIndex = math.random(1, numOfBodys)
833 if oldStyle ~= nil then
834 if aiStyle.selectedModelIndex == oldStyle.selectedModelIndex then
835 local oldBodyIndex = oldStyle.selectedBodyIndex
836 if numOfBodys > 1 then
837 while aiBodyIndex == oldBodyIndex do
838 aiBodyIndex = math.random(1, numOfBodys)
839 end
840 end
841 end
842 end
843 aiStyle:setBody(aiBodyIndex)
844
845 aiStyle:setColor(math.random(1, #g_playerColors))
846 aiStyle:setHair(math.random(1, #aiStyle.hairs.styles))
847 aiStyle:setJacket(math.random(0, #aiStyle.jackets))
848 end
849end

setVehicleCharacter

Description
Definition
setVehicleCharacter()
Code
802function Enterable:setVehicleCharacter(xmlFilename, playerStyle)
803 local spec = self.spec_enterable
804 if spec.vehicleCharacter ~= nil then
805 spec.vehicleCharacter:delete()
806 spec.vehicleCharacter:loadCharacter(xmlFilename, playerStyle)
807 spec.vehicleCharacter:updateVisibility()
808 spec.vehicleCharacter:updateIKChains()
809
810 spec.additionalCharacterActive = false
811 end
812
813 SpecializationUtil.raiseEvent(self, "onVehicleCharacterChanged", spec.vehicleCharacter)
814end

updateCharacterTargetNodeModifier

Description
Definition
updateCharacterTargetNodeModifier()
Code
475function Enterable:updateCharacterTargetNodeModifier(dt, modifier)
476 local node = modifier.parent
477 local poseId = modifier.poseId
478 for _,state in pairs(modifier.states) do
479 -- check if the rotation is different than the rotation on loading
480 local x, y, z = getRotation(state.referenceNode)
481 local refX, refY, refZ = unpack(state.defaultRotation)
482
483 if math.abs(x-refX) + math.abs(y-refY) + math.abs(z-refZ) > 0.001 then
484 node = state.node
485 poseId = state.poseId or poseId
486 end
487
488 -- check if the translation is different than the translation on loading
489 x, y, z = getTranslation(state.referenceNode)
490 refX, refY, refZ = unpack(state.defaultTranslation)
491
492 if math.abs(x-refX) + math.abs(y-refY) + math.abs(z-refZ) > 0.001 then
493 node = state.node
494 poseId = state.poseId or poseId
495 end
496
497 -- align the target node to the direction reference node
498 if node == state.node and state.directionReferenceNode ~= nil then
499 local wx, wy, wz = getWorldTranslation(state.directionReferenceNode)
500 local lx, ly, lz = getTranslation(state.node)
501 local dx, dy, dz = worldToLocal(getParent(state.node), wx, wy, wz)
502 setDirection(state.node, dx-lx, dy-ly, dz-lz, 0, 1, 0)
503 end
504 end
505
506 local isDirty = modifier.transitionAlpha < 1
507 local allowSwitch = node ~= modifier.parent
508
509 if not allowSwitch then
510 modifier.transitionIdleTime = modifier.transitionIdleTime + dt
511
512 if modifier.transitionIdleTime > modifier.transitionIdleDelay then
513 allowSwitch = true
514 modifier.transitionIdleTime = 0
515 end
516 end
517
518 if allowSwitch and getParent(modifier.node) ~= node then
519 local transStartPos = {localToLocal(modifier.node, node, 0,0,0)}
520 local transEndPos = {0, 0, 0}
521 if node == modifier.parent then
522 transEndPos = modifier.translationOffset
523 end
524 modifier.transitionStartPos = transStartPos
525 modifier.transitionEndPos = transEndPos
526
527 if math.abs(transEndPos[1] - transStartPos[1]) < 0.001 and math.abs(transEndPos[2] - transStartPos[2]) < 0.001 and math.abs(transEndPos[3] - transStartPos[3]) < 0.001 then
528 modifier.transitionAlpha = 1.0
529 else
530 modifier.transitionAlpha = 0
531 end
532
533 isDirty = true
534
535 local rx,ry,rz = localRotationToLocal(getParent(modifier.node), node, 0,0,0)
536 modifier.transitionStartQuat = {mathEulerToQuaternion(rx, ry, rz)}
537 modifier.transitionEndQuat = {0, 0, 0, 1}
538 if node == modifier.parent then
539 modifier.transitionEndQuat = {mathEulerToQuaternion(unpack(modifier.rotationOffset))}
540 end
541
542 link(node, modifier.node)
543
544 if poseId ~= nil then
545 local character = self:getVehicleCharacter()
546 if character ~= nil then
547 local chain = IKUtil.getIKChainByTarget(character.ikChains, modifier.node)
548 if chain ~= nil then
549 IKUtil.setIKChainPose(character.ikChains, chain.id, poseId)
550 end
551 end
552 end
553 end
554
555 if isDirty then
556 modifier.transitionAlpha = math.min(1.0, modifier.transitionAlpha + (dt/modifier.transitionTime))
557
558 local x,y,z = MathUtil.vector3ArrayLerp(modifier.transitionStartPos, modifier.transitionEndPos, modifier.transitionAlpha)
559 setTranslation(modifier.node, x,y,z)
560
561 local qx,qy,qz,qw = MathUtil.slerpQuaternionShortestPath(modifier.transitionStartQuat[1], modifier.transitionStartQuat[2], modifier.transitionStartQuat[3], modifier.transitionStartQuat[4],
562 modifier.transitionEndQuat[1], modifier.transitionEndQuat[2], modifier.transitionEndQuat[3], modifier.transitionEndQuat[4],
563 modifier.transitionAlpha)
564 setQuaternion(modifier.node, qx,qy,qz,qw)
565 end
566end