LUADOC - Farming Simulator 19

Script v1.7.1.0

Engine v1.7.1.0

Foundation Reference

Rideable

Description
Specialization class for Rideables
XML Configuration Parameters
vehicle.rideable#speedBackwardsmax speed in gait type backwards (m/s)
vehicle.rideable#speedWalkmax speed in gait type walk (m/s)
vehicle.rideable#speedTrotmax speed in gait type trot (m/s)
vehicle.rideable#speedGallopmax speed in gait type gallop (m/s)
vehicle.rideable#turnAnglemax turn speed (deg/s)

Functions

abandonCheck

Description
Definition
abandonCheck()
Code
1279function Rideable:abandonCheck(dt)
1280 local spec = self.spec_rideable
1281
1282 if spec.animal == nil then
1283 return
1284 end
1285 local isOnHusbandry = spec.animal:isOnHusbandyGround()
1286 if isOnHusbandry then
1287 self:removeRideable()
1288 g_currentMission:addIngameNotification(FSBaseMission.INGAME_NOTIFICATION_OK, string.format(g_i18n:getText("ingameNotification_horseInStable"), spec.animal:getName()))
1289 return
1290 end
1291
1292 -- remove animal as soon as all players are out of range
1293 local range = 250
1294 local isPlayerInRange = false
1295 for _, player in pairs(g_currentMission.players) do
1296 if player.isControlled then
1297 local distance = calcDistanceFrom(self.rootNode, player.rootNode)
1298 if distance < range then
1299 isPlayerInRange = true
1300 break
1301 end
1302 end
1303 end
1304
1305 if not isPlayerInRange then
1306 for _, enterable in pairs(g_currentMission.enterables) do
1307 if enterable.spec_enterable ~= nil and enterable.spec_enterable.isControlled then
1308 local distance = calcDistanceFrom(self.rootNode, enterable.rootNode)
1309 if distance < range then
1310 isPlayerInRange = true
1311 break
1312 end
1313 end
1314 end
1315 end
1316
1317 if isPlayerInRange then
1318 spec.abandonTimer = spec.abandonTimerDuration
1319 else
1320 spec.abandonTimer = spec.abandonTimer - dt
1321 if spec.abandonTimer <= 0 then
1322 self:removeRideable()
1323 g_currentMission:addIngameNotification(FSBaseMission.INGAME_NOTIFICATION_OK, string.format(g_i18n:getText("ingameNotification_horseInStable"), spec.animal:getName()))
1324 end
1325 end
1326
1327 if spec.abandonTimer > 0 then
1328 self:raiseActive()
1329 end
1330end

actionEventAccelerate

Description
Callback on accelerate event
Definition
actionEventAccelerate(table self, string actionName, float inputValue, string callbackState, bool isAnalog)
Arguments
tableselfinstance
stringactionNameaction name
floatinputValueinput value
stringcallbackState
boolisAnalogtrue if input is analog
Code
1068function Rideable.actionEventAccelerate(self, actionName, inputValue, callbackState, isAnalog)
1069 local spec = self.spec_rideable
1070 local enterable = self.spec_enterable
1071
1072 if enterable.isEntered and enterable.isControlled and spec.haltTimer <= 0 and spec.isOnGround then
1073 spec.inputValues.currentGait = math.min(spec.inputValues.currentGait + 1, Rideable.GAITTYPES.MAX)
1074 end
1075end

actionEventBrake

Description
Callback on brake event
Definition
actionEventBrake(table self, string actionName, float inputValue, string callbackState, bool isAnalog)
Arguments
tableselfinstance
stringactionNameaction name
floatinputValueinput value
stringcallbackState
boolisAnalogtrue if input is analog
Code
1084function Rideable.actionEventBrake(self, actionName, inputValue, callbackState, isAnalog)
1085 local spec = self.spec_rideable
1086 if self:getIsEntered() and spec.haltTimer <= 0 and spec.isOnGround then
1087 spec.inputValues.currentGait = math.max(spec.inputValues.currentGait - 1, 1)
1088 end
1089end

actionEventJump

Description
Callback on jump event
Definition
actionEventJump(table self, string actionName, float inputValue, string callbackState, bool isAnalog)
Arguments
tableselfinstance
stringactionNameaction name
floatinputValueinput value
stringcallbackState
boolisAnalogtrue if input is analog
Code
1113function Rideable.actionEventJump(self, actionName, inputValue, callbackState, isAnalog)
1114 local spec = self.spec_rideable
1115
1116 local canJump = spec.isOnGround and spec.inputValues.currentGait >= Rideable.GAITTYPES.CANTER and not spec.isInWater
1117 if canJump then
1118 self:jump()
1119 end
1120end

actionEventSteer

Description
Callback on steer event
Definition
actionEventSteer(table self, string actionName, float inputValue, string callbackState, bool isAnalog)
Arguments
tableselfinstance
stringactionNameaction name
floatinputValueinput value
stringcallbackState
boolisAnalogtrue if input is analog
Code
1098function Rideable.actionEventSteer(self, actionName, inputValue, callbackState, isAnalog)
1099 local spec = self.spec_rideable
1100 if self:getIsEntered() and spec.haltTimer <= 0 then
1101 local spec = self.spec_rideable
1102 spec.inputValues.axisSteer = -inputValue
1103 end
1104end

calculateLegsDistance

Description
Gets legs distance from rootNode
Definition
calculateLegsDistance(integer left, integer right)
Arguments
integerleftleg node
integerrightleg node
Return Values
floatdistancefrom root node
Code
352function Rideable:calculateLegsDistance(leftLegNode, rightLegNode)
353 local distance = 0.0
354 if leftLegNode ~= nil and rightLegNode ~= nil then
355 local dxL, dyL, dzL = localToLocal(leftLegNode, self.rootNode, 0.0, 0.0, 0.0)
356 local dxR, dyR, dzR = localToLocal(rightLegNode, self.rootNode, 0.0, 0.0, 0.0)
357 distance = (dzL + dzR) * 0.5
358 end
359 return distance
360end

endFade

Description
Definition
endFade()
Code
483function Rideable:endFade()
484end

getCanBeReset

Description
Definition
getCanBeReset()
Code
1398function Rideable:getCanBeReset(superFunc)
1399 return false
1400end

getDirtScale

Description
Definition
getDirtScale()
Code
1242function Rideable:getDirtScale()
1243 local spec = self.spec_rideable
1244 return spec.currentDirtScale
1245end

getFullName

Description
Definition
getFullName()
Code
1392function Rideable:getFullName(superFunc)
1393 return self:getName()
1394end

getHoofSurfaceSound

Description
Definition
getHoofSurfaceSound()
Code
1196function Rideable:getHoofSurfaceSound(x, y, z, hitTerrain)
1197 local spec = self.spec_rideable
1198 local densityBits = getDensityAtWorldPos(g_currentMission.terrainDetailId, x, y, z)
1199 local hitTerrain = hitTerrain
1200
1201 local inWater = g_currentMission.waterY > y
1202
1203 if hitTerrain then
1204 local isOnField = densityBits ~= 0
1205 if isOnField then
1206 return spec.surfaceNameToSound["field"]
1207 elseif inWater then
1208 return spec.surfaceNameToSound["shallowWater"]
1209 else
1210 local _, _, _, _ , materialId = getTerrainAttributesAtWorldPos(g_currentMission.terrainRootNode, x, y, z, true, true, true, true, false)
1211 return spec.surfaceIdToSound[materialId]
1212 end
1213 else
1214 return spec.surfaceNameToSound["asphalt"]
1215 end
1216end

getName

Description
Definition
getName()
Code
1385function Rideable:getName(superFunc)
1386 local spec = self.spec_rideable
1387 return spec.animal:getName()
1388end

getPosition

Description
Definition
getPosition()
Code
1220function Rideable:getPosition()
1221 return getWorldTranslation(self.rootNode)
1222end

getRotation

Description
Definition
getRotation()
Code
1226function Rideable:getRotation()
1227 return getWorldRotation(self.rootNode)
1228end

getShaderParameter

Description
Get shader parameter on the shape node
Definition
getShaderParameter(string parameterName)
Arguments
stringparameterNameparameter name
Return Values
floatxx parameter
floatyy parameter
floatzz parameter
floatwz parameter
Code
953function Rideable:getShaderParameter(parameterName)
954 local spec = self.spec_rideable
955 local x, y, z, w = getShaderParameter(spec.meshNode, parameterName)
956 return x, y, z, w
957end

groundRaycastCallback

Description
Callback used when raycast hists an object. Updates player information so it can be used to pickup the object.
Definition
groundRaycastCallback(integer hitObjectId, float x, float y, float z, float distance)
Arguments
integerhitObjectIdscenegraph object id
floatxworld x hit position
floatyworld y hit position
floatzworld z hit position
floatdistancedistance at which the cast hit the object
Return Values
boolreturnstrue object that was hit is valid
Code
768function Rideable:groundRaycastCallback(hitObjectId, x, y, z, distance)
769 local spec = self.spec_rideable
770 if hitObjectId == self.spec_cctdrivable.cctNode then
771 return true
772 end
773 -- DebugUtil.drawSimpleDebugCube(x, y, z, 0.05, 1, 0, 0)
774 spec.groundRaycastResult.y = y
775 spec.groundRaycastResult.object = hitObjectId
776 spec.groundRaycastResult.distance = distance
777
778 return false
779end

isOnHusbandyGround

Description
Definition
isOnHusbandyGround()
Code
1265function Rideable:isOnHusbandyGround(deliveryArea)
1266 if deliveryArea ~= nil and deliveryArea.startNode ~= nil and deliveryArea.heightNode ~= nil and deliveryArea.heightNode ~= nil then
1267 local x, y, z = getWorldTranslation(self.rootNode)
1268 local xl, _, zl = worldToLocal(deliveryArea.startNode, x, y, z)
1269 local xw, _, _ = getTranslation(deliveryArea.widthNode)
1270 local _, _, zh = getTranslation(deliveryArea.heightNode)
1271 local result = (xl >= 0.0) and (zl >= 0.0) and (xl < xw) and (zl < zh)
1272 return result
1273 end
1274 return false
1275end

jump

Description
Definition
jump()
Code
676function Rideable:jump()
677 local spec = self.spec_rideable
678
679 if not self.isServer then
680 g_client:getServerConnection():sendEvent(JumpEvent:new(self))
681 end
682
683 local velY = math.sqrt(-2.0 * spec.gravity * spec.jumpHeight)
684 spec.currentSpeedY = velY
685end

onDelete

Description
Called on deleting
Definition
onDelete()
Code
364function Rideable:onDelete()
365 local spec = self.spec_rideable
366 g_soundManager:deleteSamples(spec.surfaceSounds)
367 g_soundManager:deleteSample(spec.horseStopSound)
368 g_soundManager:deleteSample(spec.horseBreathSoundsNoEffort)
369 g_soundManager:deleteSample(spec.horseBreathSoundsEffort)
370
371 for _, d in pairs(spec.hooves) do
372 ParticleUtil.deleteParticleSystem(d.psSlow)
373 ParticleUtil.deleteParticleSystem(d.psFast)
374 end
375
376 if spec.animationPlayer ~= 0 then
377 delete(spec.animationPlayer)
378 spec.animationPlayer = 0
379 end
380end

onEnterVehicle

Description
Called on enter vehicle
Definition
onEnterVehicle(bool isControlling)
Arguments
boolisControlling
Code
993function Rideable:onEnterVehicle(isControlling)
994 if self.isClient then
995 local spec = self.spec_rideable
996 spec.playerToEnter = nil
997 spec.checkPlayerToEnter = false
998
999 spec.currentSpeed = 0.0
1000 spec.currentTurnSpeed = 0.0
1001 spec.inputValues.currentGait = Rideable.GAITTYPES.STILL
1002 spec.isOnGround = false
1003
1004 -- rider animation
1005 local character = self:getVehicleCharacter()
1006 if character ~= nil and character.animationCharsetId ~= 0 and character.animationPlayer ~= 0 then
1007 for key, parameter in pairs(spec.animationParameters) do
1008 conditionalAnimationRegisterParameter(character.animationPlayer, parameter.id, parameter.type, key)
1009 end
1010 initConditionalAnimation(character.animationPlayer, character.animationCharsetId, self.configFileName, "vehicle.riderConditionalAnimation")
1011 setConditionalAnimationSpecificParameterIds(character.animationPlayer, spec.animationParameters.absForwardVelocity.id, spec.animationParameters.absYawVelocity.id)
1012
1013 link(character.thirdPersonLeftHandNode, spec.leftReinNode)
1014 link(character.thirdPersonRightHandNode, spec.rightReinNode)
1015 setVisibility(spec.reinsNode, true)
1016 self:setEquipmentVisibility(true)
1017 conditionalAnimationZeroiseTrackTimes(character.animationPlayer)
1018 conditionalAnimationZeroiseTrackTimes(spec.animationPlayer)
1019 end
1020 end
1021end

onLeaveVehicle

Description
Called on leaving vehicle
Definition
onLeaveVehicle()
Code
1025function Rideable:onLeaveVehicle()
1026 if self.isClient then
1027 local spec = self.spec_rideable
1028 spec.inputValues.currentGait = Rideable.GAITTYPES.STILL
1029 self:resetInputs()
1030 if g_currentMission.hud.fadeScreenElement:getAlpha() > 0.0 then
1031 g_currentMission:fadeScreen(-1, spec.fadeDuration, self.endFade, self)
1032 end
1033 end
1034end

onLoad

Description
Called on loading
Definition
onLoad(table savegame)
Arguments
tablesavegamesavegame
Code
127function Rideable:onLoad(savegame)
128 local spec = self.spec_rideable
129
130 -- Overwrite the Vehicle high precision setting. Otherwise the precision might lead to large jitter in speed in multiplayer
131 self.highPrecisionPositionSynchronization = true
132
133 self.isVehicleSaved = false
134 spec.currentDirtScale = 0
135 spec.abandonTimerDuration = g_gameSettings:getValue("horseAbandonTimerDuration")
136 spec.abandonTimer = spec.abandonTimerDuration
137 spec.fadeDuration = 400
138 spec.isRideableRemoved = false
139 spec.justSpawned = true
140 spec.meshNode = nil
141 spec.hairNode = nil
142 -- Animation
143 spec.animationNode = nil
144 spec.charsetId = nil
145 spec.animationPlayer = 0
146 spec.animationParameters = {}
147 spec.animationParameters.forwardVelocity = {id=1, value=0.0, type=1}
148 spec.animationParameters.verticalVelocity = {id=2, value=0.0, type=1}
149 spec.animationParameters.yawVelocity = {id=3, value=0.0, type=1}
150 spec.animationParameters.absForwardVelocity = {id=4, value=0.0, type=1}
151 spec.animationParameters.onGround = {id=5, value=false, type=0}
152 spec.animationParameters.inWater = {id=6, value=false, type=0}
153 spec.animationParameters.closeToGround = {id=7, value=false, type=0}
154 spec.animationParameters.leftRightWeight = {id=8, value=0.0, type=1}
155 spec.animationParameters.absYawVelocity = {id=9, value=0.0, type=1}
156 spec.animationParameters.halted = {id=10, value=false, type=0}
157 spec.animationParameters.smoothedForwardVelocity = {id=11, value=0.0, type=1}
158 spec.animationParameters.absSmoothedForwardVelocity = {id=12, value=0.0, type=1}
159
160 -- InputAction
161 spec.acceletateEventId = ""
162 spec.brakeEventId = ""
163 spec.steerEventId = ""
164 spec.jumpEventId = ""
165
166 -- movements
167 spec.currentTurnAngle = 0
168 spec.currentTurnSpeed = 0.0
169 spec.currentSpeed = 0.0
170 spec.currentSpeedY = 0.0
171 spec.isInWater = false
172 spec.cctMoveQueue = {}
173 spec.currentCCTPosX = 0.0
174 spec.currentCCTPosY = 0.0
175 spec.currentCCTPosZ = 0.0
176 spec.lastCCTPosX = 0.0
177 spec.lastCCTPosY = 0.0
178 spec.lastCCTPosZ = 0.0
179 spec.topSpeeds = {}
180 spec.topSpeeds[Rideable.GAITTYPES.BACKWARDS] = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.rideable#speedBackwards"), -1.0)
181 spec.topSpeeds[Rideable.GAITTYPES.STILL] = 0.0
182 spec.topSpeeds[Rideable.GAITTYPES.WALK] = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.rideable#speedWalk"), 2.5)
183 spec.topSpeeds[Rideable.GAITTYPES.CANTER] = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.rideable#speedCanter"), 3.5)
184 spec.topSpeeds[Rideable.GAITTYPES.TROT] = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.rideable#speedTrot"), 5.0)
185 spec.topSpeeds[Rideable.GAITTYPES.GALLOP] = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.rideable#speedGallop"), 10.0)
186 spec.minTurnRadius = {}
187 spec.minTurnRadius[Rideable.GAITTYPES.BACKWARDS] = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.rideable#minTurnRadiusBackwards"), 1.0)
188 spec.minTurnRadius[Rideable.GAITTYPES.STILL] = 1.0
189 spec.minTurnRadius[Rideable.GAITTYPES.WALK] = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.rideable#minTurnRadiusWalk"), 1.0)
190 spec.minTurnRadius[Rideable.GAITTYPES.CANTER] = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.rideable#minTurnRadiusCanter"), 2.5)
191 spec.minTurnRadius[Rideable.GAITTYPES.TROT] = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.rideable#minTurnRadiusTrot"), 5.0)
192 spec.minTurnRadius[Rideable.GAITTYPES.GALLOP] = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.rideable#minTurnRadiusGallop"), 10.0)
193 spec.groundRaycastResult = {}
194 spec.groundRaycastResult.y = 0.0
195 spec.groundRaycastResult.object = nil
196 spec.groundRaycastResult.distance = 0.0
197 spec.haltTimer = 0.0
198 spec.smoothedLeftRightWeight = 0.0
199 spec.interpolationDt = 16
200
201 -- interpolation
202 -- spec.interpolationTime = InterpolationTime:new(1.0)
203 -- spec.interpolatorPosition = InterpolatorPosition:new(0.0, 0.0, 0.0)
204 -- spec.interpolatorQuaternion = InterpolatorQuaternion:new(0.0, 0.0, 0.0, 1.0) -- only used on server side for rotation of camera
205 -- spec.interpolatorOnGround = InterpolatorValue:new(0.0)
206
207 -- steer
208 spec.maxAcceleration = 5 -- m/s^2
209 spec.maxDeceleration = 10 -- m/s^2
210 spec.gravity = -18.8
211
212 -- ground orientation
213 spec.frontCheckDistance = 0.0
214 spec.backCheckDistance = 0.0
215 spec.isOnGround = true
216 spec.isCloseToGround = true
217
218 assert(spec.topSpeeds[Rideable.GAITTYPES.MIN] < spec.topSpeeds[Rideable.GAITTYPES.MAX])
219 spec.maxTurnSpeed = math.rad(Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.rideable#turnSpeed"), 45.0)) -- xml: deg/s, script: rad/s
220 spec.jumpHeight = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.rideable#jumpHeight"), 2.0)
221
222 local function loadHoof(target, index, key)
223 local hoof = {}
224 hoof.node = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, key.."#node"), self.i3dMappings)
225 -- hoof.psNode = createTransformGroup("psLinkNode")
226 -- link(hoof.node, hoof.psNode)
227 hoof.onGround = false
228 hoof.psSlow = {}
229 ParticleUtil.loadParticleSystem(self.xmlFile, hoof.psSlow, key..".particleSystemSlow", getRootNode(), false, nil, self.baseDirectory)
230 hoof.psFast = {}
231 ParticleUtil.loadParticleSystem(self.xmlFile, hoof.psFast, key..".particleSystemFast", getRootNode(), false, nil, self.baseDirectory)
232 target[index] = hoof
233 end
234
235 -- Hooves
236 spec.hooves = {}
237 loadHoof(spec.hooves, Rideable.HOOVES.FRONT_LEFT, "vehicle.rideable.modelInfo.hoofFrontLeft")
238 loadHoof(spec.hooves, Rideable.HOOVES.FRONT_RIGHT, "vehicle.rideable.modelInfo.hoofFrontRight")
239 loadHoof(spec.hooves, Rideable.HOOVES.BACK_LEFT, "vehicle.rideable.modelInfo.hoofBackLeft")
240 loadHoof(spec.hooves, Rideable.HOOVES.BACK_RIGHT, "vehicle.rideable.modelInfo.hoofBackRight")
241
242 spec.frontCheckDistance = self:calculateLegsDistance(spec.hooves[Rideable.HOOVES.FRONT_LEFT].node, spec.hooves[Rideable.HOOVES.FRONT_RIGHT].node)
243 spec.backCheckDistance = self:calculateLegsDistance(spec.hooves[Rideable.HOOVES.BACK_LEFT].node, spec.hooves[Rideable.HOOVES.BACK_RIGHT].node)
244
245 spec.animationNode = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.rideable.modelInfo#animationNode"), self.i3dMappings)
246 spec.meshNode = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.rideable.modelInfo#meshNode"), self.i3dMappings)
247 spec.hairNode = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.rideable.modelInfo#hairNode"), self.i3dMappings)
248 spec.equipmentNode = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.rideable.modelInfo#equipmentNode"), self.i3dMappings)
249 spec.reinsNode = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.rideable.modelInfo#reinsNode"), self.i3dMappings)
250 spec.leftReinNode = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.rideable.modelInfo#reinLeftNode"), self.i3dMappings)
251 spec.rightReinNode = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.rideable.modelInfo#reinRightNode"), self.i3dMappings)
252 spec.leftReinParentNode = getParent(spec.leftReinNode)
253 spec.rightReinParentNode = getParent(spec.rightReinNode)
254
255 -- animation
256 if spec.animationNode ~= nil then
257 spec.charsetId = getAnimCharacterSet(spec.animationNode)
258 spec.animationPlayer = createConditionalAnimation()
259 for key, parameter in pairs(spec.animationParameters) do
260 conditionalAnimationRegisterParameter(spec.animationPlayer, parameter.id, parameter.type, key)
261 end
262 initConditionalAnimation(spec.animationPlayer, spec.charsetId, self.configFileName, "vehicle.conditionalAnimation")
263 setConditionalAnimationSpecificParameterIds(spec.animationPlayer, spec.animationParameters.absForwardVelocity.id, spec.animationParameters.absYawVelocity.id)
264 end
265
266 -- Sounds
267 spec.surfaceSounds = {}
268 spec.surfaceIdToSound = {}
269 spec.surfaceNameToSound = {}
270 spec.currentSurfaceSound = nil
271 for _, surfaceSound in pairs(g_currentMission.surfaceSounds) do
272 if surfaceSound.type == "hoofstep" and surfaceSound.sample ~= nil then
273 local sample = g_soundManager:cloneSample(surfaceSound.sample, self.components[1].node, self)
274 sample.sampleName = surfaceSound.name
275
276 table.insert(spec.surfaceSounds, sample)
277 spec.surfaceIdToSound[surfaceSound.materialId] = sample
278 spec.surfaceNameToSound[surfaceSound.name] = sample
279 end
280 end
281 spec.horseStopSound = g_soundManager:loadSampleFromXML(self.xmlFile, "vehicle.rideable.sounds", "halt", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self)
282 spec.horseBreathSoundsNoEffort = g_soundManager:loadSampleFromXML(self.xmlFile, "vehicle.rideable.sounds", "breathingNoEffort", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self)
283 spec.horseBreathSoundsEffort = g_soundManager:loadSampleFromXML(self.xmlFile, "vehicle.rideable.sounds", "breathingEffort", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self)
284 spec.horseBreathIntervalNoEffort = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.rideable.sounds#breathIntervalNoEffort"), 1.0) * 1000.0
285 spec.horseBreathIntervalEffort = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.rideable.sounds#breathIntervalEffort"), 1.0) * 1000.0
286 spec.horseBreathMinIntervalIdle = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.rideable.sounds#minBreathIntervalIdle"), 1.0) * 1000.0
287 spec.horseBreathMaxIntervalIdle = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.rideable.sounds#maxBreathIntervalIdle"), 1.0) * 1000.0
288 spec.currentBreathTimer = 0.0
289
290 -- attributes set by action events
291 spec.inputValues = {}
292 spec.inputValues.axisSteer = 0.0
293 spec.inputValues.axisSteerSend = 0.0
294 spec.inputValues.currentGait = Rideable.GAITTYPES.STILL
295 self:resetInputs()
296
297 spec.interpolatorIsOnGround = InterpolatorValue:new(0.0)
298 if self.isServer then
299 spec.interpolatorTurnAngle = InterpolatorAngle:new(0.0)
300 end
301
302 if self.isServer then
303 self.networkTimeInterpolator.maxInterpolationAlpha = 1.2
304 end
305
306 -- Network
307 spec.dirtyFlag = self:getNextDirtyFlag()
308end

onReadPositionUpdateStream

Description
Definition
onReadPositionUpdateStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
462function Rideable:onReadPositionUpdateStream(streamId, connection)
463 local spec = self.spec_rideable
464 local isOnGround = streamReadBool(streamId)
465 if isOnGround then
466 spec.interpolatorIsOnGround:setValue(1.0)
467 else
468 spec.interpolatorIsOnGround:setValue(0.0)
469 end
470end

onReadStream

Description
Called on client side on join
Definition
onReadStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
386function Rideable:onReadStream(streamId, connection)
387 local spec = self.spec_rideable
388 if connection:getIsServer() then
389 local isOnGround = streamReadBool(streamId)
390 if isOnGround then
391 spec.interpolatorIsOnGround:setValue(1.0)
392 else
393 spec.interpolatorIsOnGround:setValue(0.0)
394 end
395 end
396 if streamReadBool(streamId) then
397 local animal = NetworkUtil.readNodeObject(streamId)
398 self:setAnimal(animal)
399 end
400 if streamReadBool(streamId) then
401 local player = NetworkUtil.readNodeObject(streamId)
402 self:setPlayerToEnter(player)
403 end
404end

onReadUpdateStream

Description
Called on on update
Definition
onReadUpdateStream(integer streamId, integer timestamp, table connection)
Arguments
integerstreamIdstream ID
integertimestamptimestamp
tableconnectionconnection
Code
428function Rideable:onReadUpdateStream(streamId, timestamp, connection)
429 local spec = self.spec_rideable
430
431 if not connection:getIsServer() then
432 spec.inputValues.axisSteer = streamReadFloat32(streamId)
433 spec.inputValues.currentGait = streamReadUInt8(streamId)
434 else
435 spec.haltTimer = streamReadFloat32(streamId)
436 if spec.haltTimer > 0 then
437 spec.inputValues.currentGait = Rideable.GAITTYPES.STILL
438 spec.inputValues.axisSteerSend = 0
439 end
440 end
441end

onRegisterActionEvents

Description
Registers action events
Definition
onRegisterActionEvents()
Code
961function Rideable:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection)
962 if self.isClient then
963 local spec = self.spec_rideable
964 self:clearActionEventsTable(spec.actionEvents)
965
966 if isActiveForInputIgnoreSelection then
967 local actionEventId
968 _, actionEventId = self:addActionEvent(spec.actionEvents, InputAction.AXIS_ACCELERATE_VEHICLE, self, Rideable.actionEventAccelerate, false, true, false, true, nil)
969 g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_VERY_HIGH)
970 g_inputBinding:setActionEventTextVisibility(actionEventId, false)
971 spec.acceletateEventId = actionEventId
972
973 _, actionEventId = self:addActionEvent(spec.actionEvents, InputAction.AXIS_BRAKE_VEHICLE, self, Rideable.actionEventBrake, false, true, false, true, nil)
974 g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_HIGH)
975 g_inputBinding:setActionEventTextVisibility(actionEventId, false)
976 spec.brakeEventId = actionEventId
977
978 _, actionEventId = self:addActionEvent(spec.actionEvents, InputAction.AXIS_MOVE_SIDE_VEHICLE, self, Rideable.actionEventSteer, false, false, true, true, nil)
979 g_inputBinding:setActionEventTextVisibility(actionEventId, false)
980 spec.steerEventId = actionEventId
981
982 _, actionEventId = self:addActionEvent(spec.actionEvents, InputAction.JUMP, self, Rideable.actionEventJump, false, true, false, true, nil)
983 g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_VERY_LOW)
984 g_inputBinding:setActionEventTextVisibility(actionEventId, false)
985 spec.jumpEventId = actionEventId
986 end
987 end
988end

onSetBroken

Description
Definition
onSetBroken()
Code
635function Rideable:onSetBroken()
636 self:removeRideable()
637 self:unlinkReins()
638 local spec = self.spec_rideable
639 g_currentMission:addIngameNotification(FSBaseMission.INGAME_NOTIFICATION_OK, string.format(g_i18n:getText("ingameNotification_horseInStable"), spec.animal:getName()))
640end

onUpdate

Description
Called on on update
Definition
onUpdate(float dt, bool isActiveForInput, bool isSelected)
Arguments
floatdtdelta time
boolisActiveForInputtrue if specializations is active for input
boolisSelectedtrue if specializations is selected
Code
491function Rideable:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
492 local spec = self.spec_rideable
493
494 if spec.playerToEnter ~= nil and spec.checkPlayerToEnter then
495 if spec.playerToEnter == g_currentMission.player then
496 g_currentMission:requestToEnterVehicle(self)
497 spec.checkPlayerToEnter = false
498 end
499 end
500
501 local isEntered = self:getIsEntered()
502 local isControlled = self:getIsControlled()
503
504 if isEntered then
505 if isActiveForInputIgnoreSelection then
506 self:updateInputText()
507 end
508 if not self.isServer then
509 spec.inputValues.axisSteerSend = spec.inputValues.axisSteer
510 self:raiseDirtyFlags(spec.dirtyFlag)
511 self:resetInputs()
512 end
513 end
514
515 if spec.isOnGround and spec.justSpawned then
516 spec.justSpawned = false
517 if (not spec.checkPlayerToEnter and isEntered) or (spec.checkPlayerToEnter and spec.playerToEnter == g_currentMission.player) then
518 g_currentMission:fadeScreen(-1, spec.fadeDuration, self.endFade, self)
519 end
520 end
521
522 self:updateAnimation(dt)
523 if self.isClient then
524 self:updateSound(dt)
525 end
526
527 if self.isServer then
528 self:updateFitness(dt)
529 self:updateDirt(dt)
530 end
531
532 if spec.haltTimer > 0 then
533 spec.inputValues.currentGait = Rideable.GAITTYPES.STILL
534 spec.haltTimer = spec.haltTimer - dt
535 end
536
537 if self.isServer then
538 if not isEntered and not isControlled and spec.playerToEnter == nil then
539 self:abandonCheck(dt)
540 end
541 end
542 self:raiseActive()
543end

onUpdateInterpolation

Description
Definition
onUpdateInterpolation()
Code
547function Rideable:onUpdateInterpolation(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
548 local spec = self.spec_rideable
549
550 if self.isServer then
551 if not self:getIsControlled() then
552 spec.inputValues.currentGait = Rideable.GAITTYPES.STILL
553 end
554 -- for key, moveInfo in pairs(spec.cctMoveQueue) do
555 -- print(string.format("-- [Rideable:onUpdateInterpolation][A][%d]\t%d\t%d\t%d\t%s\t%.6f", g_updateLoopIndex, getPhysicsUpdateIndex(), key, moveInfo.physicsIndex, tostring(getIsPhysicsUpdateIndexSimulated(moveInfo.physicsIndex)), moveInfo.dt))
556 -- end
557
558 local interpolationDt = dt
559 local oldestMoveInfo = spec.cctMoveQueue[1]
560 if oldestMoveInfo ~= nil and getIsPhysicsUpdateIndexSimulated(oldestMoveInfo.physicsIndex) then
561 interpolationDt = oldestMoveInfo.dt
562 end
563 spec.interpolationDt = interpolationDt
564
565 self:testCCTMove(interpolationDt)
566 self:updateKinematic(dt)
567
568 if self:getIsEntered() then
569 self:resetInputs()
570 end
571
572 local component = self.components[1]
573 local x,y,z = self:getCCTWorldTranslation()
574 component.networkInterpolators.position:setTargetPosition(x,y,z)
575 spec.interpolatorTurnAngle:setTargetAngle(spec.currentTurnAngle)
576 spec.interpolatorIsOnGround:setTargetValue(self:getIsCCTOnGround() and 1.0 or 0.0)
577
578 -- use 75 or if dt > 75 then dt + 20
579 local phaseDuration = interpolationDt + 30
580
581
582 self.networkTimeInterpolator:startNewPhase(phaseDuration)
583 self.networkTimeInterpolator:update(interpolationDt)
584
585 -- local deltax, deltay, deltaz = component.networkInterpolators.position.targetPositionX - component.networkInterpolators.position.lastPositionX, component.networkInterpolators.position.targetPositionY - component.networkInterpolators.position.lastPositionY, component.networkInterpolators.position.targetPositionZ - component.networkInterpolators.position.lastPositionZ
586 -- local deltamag = math.sqrt(deltax*deltax+deltay*deltay+deltaz*deltaz)
587 -- print(string.format("-- [Rideable:onUpdateInterpolation][B][%d]\t%.6f\t%.6f\t%d\t%.6f\t%.6f\t%.6f\t%.6f\t%.6f\t%.6f\t%.6f\t%.6f\t%.6f\t%.6f\t%.6f\t%.6f", g_updateLoopIndex, dt, interpolationDt, getPhysicsUpdateIndex(), self.networkTimeInterpolator.interpolationAlpha, self.networkTimeInterpolator.interpolationDuration, component.networkInterpolators.position.targetPositionX, component.networkInterpolators.position.targetPositionY, component.networkInterpolators.position.targetPositionZ, component.networkInterpolators.position.lastPositionX, component.networkInterpolators.position.lastPositionY, component.networkInterpolators.position.lastPositionZ, deltax, deltay, deltaz, deltamag))
588
589 local x, y, z = component.networkInterpolators.position:getInterpolatedValues(self.networkTimeInterpolator.interpolationAlpha)
590 setTranslation(self.rootNode, x, y, z)
591
592 local turnAngle = spec.interpolatorTurnAngle:getInterpolatedValue(self.networkTimeInterpolator.interpolationAlpha)
593 local dirX, dirY, dirZ = localDirectionToWorld(self.rootNode, 0.0, 0.0, 1.0)
594 dirX, dirZ = math.sin(turnAngle), math.cos(turnAngle)
595
596 -- rescale direction to length, keeping the original y (but keep it to some reasonable value)
597 local scale = math.sqrt(1-math.min(dirY*dirY, 0.9))
598 dirX = dirX * scale
599 dirZ = dirZ * scale
600 setDirection(self.rootNode, dirX, dirY, dirZ, 0,1,0)
601
602 if self.networkTimeInterpolator.isDirty then
603 self:raiseActive()
604 end
605 end
606
607 local isOnGroundFloat = spec.interpolatorIsOnGround:getInterpolatedValue(self.networkTimeInterpolator:getAlpha())
608 spec.isOnGround = isOnGroundFloat > 0.9
609 spec.isCloseToGround = false
610
611 if spec.isOnGround and (math.abs(spec.currentSpeed) > 0.001 or math.abs(spec.currentTurnSpeed) > 0.001) then
612 -- orientation from ground
613 local posX, posY, posZ = getWorldTranslation(self.rootNode)
614 local dirX, dirY, dirZ = localDirectionToWorld(self.rootNode, 0.0, 0.0, 1.0)
615 local fx, fy, fz = posX + dirX * spec.frontCheckDistance, posY + dirY * spec.frontCheckDistance, posZ + dirZ * spec.frontCheckDistance
616 spec.groundRaycastResult.y = fy + Rideable.GROUND_RAYCAST_OFFSET - Rideable.GROUND_RAYCAST_MAXDISTANCE
617 raycastClosest(fx, fy + Rideable.GROUND_RAYCAST_OFFSET, fz, 0.0, -1.0, 0.0, "groundRaycastCallback", Rideable.GROUND_RAYCAST_MAXDISTANCE, self, Rideable.GROUND_RAYCAST_COLLISIONMASK)
618 fy = spec.groundRaycastResult.y
619 local bx, by, bz = posX + dirX * spec.backCheckDistance, posY + dirY * spec.backCheckDistance, posZ + dirZ * spec.backCheckDistance
620 spec.groundRaycastResult.y = by + Rideable.GROUND_RAYCAST_OFFSET - Rideable.GROUND_RAYCAST_MAXDISTANCE
621 raycastClosest(bx, by + Rideable.GROUND_RAYCAST_OFFSET, bz, 0.0, -1.0, 0.0, "groundRaycastCallback", Rideable.GROUND_RAYCAST_MAXDISTANCE, self, Rideable.GROUND_RAYCAST_COLLISIONMASK)
622 by = spec.groundRaycastResult.y
623 local dx, dy, dz = fx - bx, fy - by, fz - bz
624 setDirection(self.rootNode, dx, dy, dz, 0, 1, 0)
625 else
626 local posX, posY, posZ = getWorldTranslation(self.rootNode)
627 spec.groundRaycastResult.distance = Rideable.GROUND_RAYCAST_MAXDISTANCE
628 raycastClosest(posX, posY, posZ, 0.0, -1.0, 0.0, "groundRaycastCallback", Rideable.GROUND_RAYCAST_MAXDISTANCE, self, Rideable.GROUND_RAYCAST_COLLISIONMASK)
629 spec.isCloseToGround = spec.groundRaycastResult.distance < 1.25
630 end
631end

onWritePositionUpdateStream

Description
Definition
onWritePositionUpdateStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
476function Rideable:onWritePositionUpdateStream(streamId, connection, dirtyMask)
477 local spec = self.spec_rideable
478 streamWriteBool(streamId, spec.isOnGround)
479end

onWriteStream

Description
Called on client side on join
Definition
onWriteStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
410function Rideable:onWriteStream(streamId, connection)
411 local spec = self.spec_rideable
412 if not connection:getIsServer() then
413 streamWriteBool(streamId, spec.isOnGround)
414 end
415 if streamWriteBool(streamId, spec.animal ~= nil) then
416 NetworkUtil.writeNodeObject(streamId, spec.animal)
417 end
418 if streamWriteBool(streamId, spec.playerToEnter ~= nil) then
419 NetworkUtil.writeNodeObject(streamId, spec.playerToEnter)
420 end
421end

onWriteUpdateStream

Description
Called on on update
Definition
onWriteUpdateStream(integer streamId, table connection, integer dirtyMask)
Arguments
integerstreamIdstream ID
tableconnectionconnection
integerdirtyMaskdirty mask
Code
448function Rideable:onWriteUpdateStream(streamId, connection, dirtyMask)
449 local spec = self.spec_rideable
450 if connection:getIsServer() then
451 streamWriteFloat32(streamId, spec.inputValues.axisSteerSend)
452 streamWriteUInt8(streamId, spec.inputValues.currentGait)
453 else
454 streamWriteFloat32(streamId, spec.haltTimer)
455 end
456end

prerequisitesPresent

Description
Checks if all prerequisite specializations are loaded
Definition
prerequisitesPresent(table specializations)
Arguments
tablespecializationsspecializations
Return Values
booleanhasPrerequisitetrue if all prerequisite specializations are loaded
Code
53function Rideable.prerequisitesPresent(specializations)
54 return SpecializationUtil.hasSpecialization(CCTDrivable, specializations)
55end

registerEventListeners

Description
Registers event listeners
Definition
registerEventListeners(string vehicleType)
Arguments
stringvehicleTypetype of vehicle
Code
96function Rideable.registerEventListeners(vehicleType)
97 SpecializationUtil.registerEventListener(vehicleType, "onLoad", Rideable)
98 SpecializationUtil.registerEventListener(vehicleType, "onDelete", Rideable)
99 SpecializationUtil.registerEventListener(vehicleType, "onReadStream", Rideable)
100 SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", Rideable)
101 SpecializationUtil.registerEventListener(vehicleType, "onReadUpdateStream", Rideable)
102 SpecializationUtil.registerEventListener(vehicleType, "onWriteUpdateStream", Rideable)
103 SpecializationUtil.registerEventListener(vehicleType, "onReadPositionUpdateStream", Rideable)
104 SpecializationUtil.registerEventListener(vehicleType, "onWritePositionUpdateStream", Rideable)
105 SpecializationUtil.registerEventListener(vehicleType, "onUpdate", Rideable)
106 SpecializationUtil.registerEventListener(vehicleType, "onUpdateInterpolation", Rideable)
107 SpecializationUtil.registerEventListener(vehicleType, "onRegisterActionEvents", Rideable)
108 SpecializationUtil.registerEventListener(vehicleType, "onEnterVehicle", Rideable)
109 SpecializationUtil.registerEventListener(vehicleType, "onLeaveVehicle", Rideable)
110 SpecializationUtil.registerEventListener(vehicleType, "onSetBroken", Rideable)
111end

registerFunctions

Description
Registers functions
Definition
registerFunctions(string vehicleType)
Arguments
stringvehicleTypetype of vehicle
Code
60function Rideable.registerFunctions(vehicleType)
61 SpecializationUtil.registerFunction(vehicleType, "jump", Rideable.jump)
62 SpecializationUtil.registerFunction(vehicleType, "resetInputs", Rideable.resetInputs)
63 SpecializationUtil.registerFunction(vehicleType, "updateKinematic", Rideable.updateKinematic)
64 SpecializationUtil.registerFunction(vehicleType, "testCCTMove", Rideable.testCCTMove)
65 SpecializationUtil.registerFunction(vehicleType, "updateAnimation", Rideable.updateAnimation)
66 SpecializationUtil.registerFunction(vehicleType, "updateSound", Rideable.updateSound)
67 SpecializationUtil.registerFunction(vehicleType, "updateFitness", Rideable.updateFitness)
68 SpecializationUtil.registerFunction(vehicleType, "updateDirt", Rideable.updateDirt)
69 SpecializationUtil.registerFunction(vehicleType, "calculateLegsDistance", Rideable.calculateLegsDistance)
70 SpecializationUtil.registerFunction(vehicleType, "setWorldPositionQuat", Rideable.setWorldPositionQuat)
71 SpecializationUtil.registerFunction(vehicleType, "setShaderParameter", Rideable.setShaderParameter)
72 SpecializationUtil.registerFunction(vehicleType, "getShaderParameter", Rideable.getShaderParameter)
73 SpecializationUtil.registerFunction(vehicleType, "updateFootsteps", Rideable.updateFootsteps)
74 SpecializationUtil.registerFunction(vehicleType, "getPosition", Rideable.getPosition)
75 SpecializationUtil.registerFunction(vehicleType, "getRotation", Rideable.getRotation)
76 SpecializationUtil.registerFunction(vehicleType, "setDirtScale", Rideable.setDirtScale)
77 SpecializationUtil.registerFunction(vehicleType, "getDirtScale", Rideable.getDirtScale)
78 SpecializationUtil.registerFunction(vehicleType, "setFitnessChangedCallback", Rideable.setFitnessChangedCallback)
79 SpecializationUtil.registerFunction(vehicleType, "setDirtChangedCallback", Rideable.setDirtChangedCallback)
80 SpecializationUtil.registerFunction(vehicleType, "isOnHusbandyGround", Rideable.isOnHusbandyGround)
81 SpecializationUtil.registerFunction(vehicleType, "setEquipmentVisibility", Rideable.setEquipmentVisibility)
82 SpecializationUtil.registerFunction(vehicleType, "abandonCheck", Rideable.abandonCheck)
83 SpecializationUtil.registerFunction(vehicleType, "getHoofSurfaceSound", Rideable.getHoofSurfaceSound)
84 SpecializationUtil.registerFunction(vehicleType, "removeRideable", Rideable.removeRideable)
85 SpecializationUtil.registerFunction(vehicleType, "setAnimal", Rideable.setAnimal)
86 SpecializationUtil.registerFunction(vehicleType, "groundRaycastCallback", Rideable.groundRaycastCallback)
87 SpecializationUtil.registerFunction(vehicleType, "unlinkReins", Rideable.unlinkReins)
88 SpecializationUtil.registerFunction(vehicleType, "updateInputText", Rideable.updateInputText)
89 SpecializationUtil.registerFunction(vehicleType, "setPlayerToEnter", Rideable.setPlayerToEnter)
90 SpecializationUtil.registerFunction(vehicleType, "endFade", Rideable.endFade)
91end

registerOverwrittenFunctions

Description
Definition
registerOverwrittenFunctions()
Code
115function Rideable.registerOverwrittenFunctions(vehicleType)
116 SpecializationUtil.registerOverwrittenFunction(vehicleType, "setWorldPosition", Rideable.setWorldPosition)
117 SpecializationUtil.registerOverwrittenFunction(vehicleType, "setWorldPositionQuaternion", Rideable.setWorldPositionQuaternion)
118 SpecializationUtil.registerOverwrittenFunction(vehicleType, "updateVehicleSpeed", Rideable.updateVehicleSpeed)
119 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getName", Rideable.getName)
120 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getFullName", Rideable.getFullName)
121 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getCanBeReset", Rideable.getCanBeReset)
122end

removeRideable

Description
Definition
removeRideable()
Code
1373function Rideable:removeRideable()
1374 local spec = self.spec_rideable
1375 if not spec.isRideableRemoved then
1376 spec.isRideableRemoved = true
1377
1378 local husbandry = spec.animal:getOwner()
1379 husbandry:removeRideable(spec.animal:getVisualId())
1380 end
1381end

resetInputs

Description
Resets all inputs
Definition
resetInputs()
Code
689function Rideable:resetInputs()
690 local spec = self.spec_rideable
691 spec.inputValues.axisSteer = 0
692end

setAnimal

Description
Definition
setAnimal()
Code
1334function Rideable:setAnimal(animal)
1335 local spec = self.spec_rideable
1336 spec.animal = animal
1337
1338 if animal ~= nil then
1339 -- set dirt
1340 local x, y, z, w = getShaderParameter(spec.meshNode, "RDT")
1341 local dirt = animal:getDirtScale()
1342 setShaderParameter(spec.meshNode, "RDT", x, dirt, z, w, false)
1343
1344 -- set texture
1345 local x, y, _, _ = getShaderParameter(spec.meshNode, "atlasInvSizeAndOffsetUV")
1346 local numTilesU = 1 / x
1347 local numTilesV = 1 / y
1348 local subType = animal:getSubType()
1349 local tileUIndex = subType.texture.tileUIndex
1350 local tileVIndex = subType.texture.tileVIndex
1351 local tileU = tileUIndex / numTilesU
1352 local tileV = tileVIndex / numTilesV
1353
1354 setShaderParameter(spec.meshNode, "atlasInvSizeAndOffsetUV", x, y, tileU, tileV, false)
1355
1356 if spec.hairNode ~= nil then
1357 local x, y, _, _ = getShaderParameter(spec.hairNode, "atlasInvSizeAndOffsetUV")
1358 setShaderParameter(spec.hairNode, "atlasInvSizeAndOffsetUV", x, y, tileU, tileV, false)
1359 end
1360 end
1361end

setDirtChangedCallback

Description
Definition
setDirtChangedCallback()
Code
1249function Rideable:setDirtChangedCallback(dirtChangedCallbackFunc, dirtChangedCallbackTarget)
1250 local spec = self.spec_rideable
1251 spec.dirtChangedCallbackFunc = dirtChangedCallbackFunc
1252 spec.dirtChangedCallbackTarget = dirtChangedCallbackTarget
1253end

setDirtScale

Description
Definition
setDirtScale()
Code
1232function Rideable:setDirtScale(scale)
1233 local spec = self.spec_rideable
1234 spec.currentDirtScale = scale
1235 local x, _, z, w = getShaderParameter(spec.meshNode, "RDT")
1236 I3DUtil.setShaderParameterRec(spec.meshNode, "RDT", x, spec.currentDirtScale, z, w)
1237 I3DUtil.setShaderParameterRec(spec.hairNode, "RDT", x, spec.currentDirtScale, z, w)
1238end

setEquipmentVisibility

Description
Called on leaving the vehicle
Definition
setEquipmentVisibility()
Code
1050function Rideable:setEquipmentVisibility(val)
1051 if self.isClient then
1052 local spec = self.spec_rideable
1053
1054 if spec.equipmentNode ~= nil then
1055 setVisibility(spec.equipmentNode, val)
1056 setVisibility(spec.reinsNode, val)
1057 end
1058 end
1059end

setFitnessChangedCallback

Description
Definition
setFitnessChangedCallback()
Code
1257function Rideable:setFitnessChangedCallback(fitnessChangedCallbackFunc, fitnessChangedCallbackTarget)
1258 local spec = self.spec_rideable
1259 spec.fitnessChangedCallbackFunc = fitnessChangedCallbackFunc
1260 spec.fitnessChangedCallbackTarget = fitnessChangedCallbackTarget
1261end

setPlayerToEnter

Description
Definition
setPlayerToEnter()
Code
1364function Rideable:setPlayerToEnter(player)
1365 local spec = self.spec_rideable
1366 spec.playerToEnter = player
1367 spec.checkPlayerToEnter = true
1368 self:raiseActive()
1369end

setShaderParameter

Description
Set shader parameter on the shape node
Definition
setShaderParameter(float x, float y, float z, float w, string parameterName)
Arguments
floatxx parameter
floatyy parameter
floatzz parameter
floatwz parameter
stringparameterNameparameter name
Code
940function Rideable:setShaderParameter(x, y, z, w, parameterName)
941 local spec = self.spec_rideable
942 I3DUtil.setShaderParameterRec(spec.meshNode, parameterName, x, y, z, w)
943 I3DUtil.setShaderParameterRec(spec.hairNode, parameterName, x, y, z, w)
944end

setWorldPositionQuat

Description
Set world position and quaternion rotation of component
Definition
setWorldPositionQuat(float x, float y, float z, float qx, float qy, float qz, float qw, Integer i, boolean changeInterp)
Arguments
floatxx position
floatyy position
floatzz position
floatqxx rotation
floatqyy rotation
floatqzz rotation
floatqww rotation
Integeriindex if component
booleanchangeInterpchange interpolation
Code
923function Rideable:setWorldPositionQuat(x,y,z, qx,qy,qz,qw, changeInterp)
924 setWorldTranslation(self.rootNode, x,y,z)
925 setWorldQuaternion(self.rootNode, qx,qy,qz,qw)
926 if changeInterp then
927 local spec = self.spec_rideable
928 spec.networkInterpolators.position:setPosition(x,y,z)
929 spec.networkInterpolators.quaternion:setQuaternion(qx, qy, qz, qw)
930 end
931end

testCCTMove

Description
Check if a requested CCT move was successful. We need a range for the error because of possible huge fps fluctuation.
Definition
testCCTMove()
Code
645function Rideable:testCCTMove(dt)
646 local spec = self.spec_rideable
647 spec.lastCCTPosX, spec.lastCCTPosY, spec.lastCCTPosZ = spec.currentCCTPosX, spec.currentCCTPosY, spec.currentCCTPosZ
648 spec.currentCCTPosX, spec.currentCCTPosY, spec.currentCCTPosZ = getWorldTranslation(self.spec_cctdrivable.cctNode)
649
650 local expectedMovementX, expectedMovementZ = 0,0
651
652 while spec.cctMoveQueue[1] ~= nil and getIsPhysicsUpdateIndexSimulated(spec.cctMoveQueue[1].physicsIndex) do
653 expectedMovementX = expectedMovementX + spec.cctMoveQueue[1].moveX
654 expectedMovementZ = expectedMovementZ + spec.cctMoveQueue[1].moveZ
655 table.remove(spec.cctMoveQueue, 1)
656 end
657
658 local expectedMovement = math.sqrt(expectedMovementX * expectedMovementX + expectedMovementZ * expectedMovementZ)
659 if expectedMovement > 0.001*dt then -- only check if we are supposed to move faster than 3.6km/h
660 local movementX = spec.currentCCTPosX - spec.lastCCTPosX
661 local movementZ = spec.currentCCTPosZ - spec.lastCCTPosZ
662 local movement = math.sqrt(movementX * movementX + movementZ * movementZ)
663 if movement <= expectedMovement*0.7 and spec.haltTimer <= 0.0 then
664 -- print(string.format("-- [Rideable:testCCTMove][%d] movement(%.3f), expectedMovement(%.3f) haltTimer(%.3f)", g_updateLoopIndex, movement, expectedMovement, spec.haltTimer))
665 spec.inputValues.currentGait = Rideable.GAITTYPES.STILL
666 spec.haltTimer = 900
667 if spec.horseStopSound ~= nil then
668 g_soundManager:playSample(spec.horseStopSound)
669 end
670 end
671 end
672end

unlinkReins

Description
Definition
unlinkReins()
Code
1038function Rideable:unlinkReins()
1039 if self.isClient then
1040 local spec = self.spec_rideable
1041
1042 link(spec.leftReinParentNode, spec.leftReinNode)
1043 link(spec.rightReinParentNode, spec.rightReinNode)
1044 setVisibility(spec.reinsNode, false)
1045 end
1046end

updateAnimation

Description
Updates the parameters that will drive the animation
Definition
updateAnimation(float dt)
Arguments
floatdtdelta time in ms
Code
784function Rideable:updateAnimation(dt)
785 local spec = self.spec_rideable
786 local params = spec.animationParameters
787 local speed = self.lastSignedSpeedReal * 1000.0
788 local smoothedSpeed = self.lastSignedSpeed * 1000.0
789 speed = MathUtil.clamp(speed, spec.topSpeeds[Rideable.GAITTYPES.BACKWARDS], spec.topSpeeds[Rideable.GAITTYPES.MAX])
790 smoothedSpeed = MathUtil.clamp(smoothedSpeed, spec.topSpeeds[Rideable.GAITTYPES.BACKWARDS], spec.topSpeeds[Rideable.GAITTYPES.MAX])
791
792 local turnSpeed
793 if self.isServer then
794 turnSpeed = (spec.interpolatorTurnAngle.targetValue - spec.interpolatorTurnAngle.lastValue) / (self.networkTimeInterpolator.interpolationDuration * 0.001)
795 else
796 local interpQuat = self.components[1].networkInterpolators.quaternion
797 local lastDirX, lastDirY, lastDirZ = mathQuaternionRotateVector(interpQuat.lastQuaternionX, interpQuat.lastQuaternionY, interpQuat.lastQuaternionZ, interpQuat.lastQuaternionW, 0,0,1)
798 local targetDirX, targetDirY, targetDirZ = mathQuaternionRotateVector(interpQuat.targetQuaternionX, interpQuat.targetQuaternionY, interpQuat.targetQuaternionZ, interpQuat.targetQuaternionW, 0,0,1)
799 local lastTurnAngle = MathUtil.getYRotationFromDirection(lastDirX, lastDirZ)
800 local targetTurnAngle = MathUtil.getYRotationFromDirection(targetDirX, targetDirZ)
801 local turnAngleDiff = targetTurnAngle - lastTurnAngle
802 -- normalize to -180,180deg
803 if turnAngleDiff > math.pi then
804 turnAngleDiff = turnAngleDiff - 2*math.pi
805 elseif turnAngleDiff < -math.pi then
806 turnAngleDiff = turnAngleDiff + 2*math.pi
807 end
808 turnSpeed = turnAngleDiff / (self.networkTimeInterpolator.interpolationDuration * 0.001)
809 end
810
811 local interpPos = self.components[1].networkInterpolators.position
812 local speedY = (interpPos.targetPositionY - interpPos.lastPositionY) / (self.networkTimeInterpolator.interpolationDuration * 0.001)
813
814
815 local leftRightWeight = 0
816 if math.abs(speed) > 0.01 then
817 local closestGait = Rideable.GAITTYPES.STILL
818 local closestDiff = math.huge
819 for i=1,Rideable.GAITTYPES.MAX do
820 local diff = math.abs(speed - spec.topSpeeds[i])
821 if diff < closestDiff then
822 closestGait = i
823 closestDiff = diff
824 end
825 end
826 local minTurnRadius = spec.minTurnRadius[closestGait]
827 leftRightWeight = minTurnRadius * turnSpeed / speed
828 else
829 leftRightWeight = turnSpeed / spec.maxTurnSpeed
830 end
831 if leftRightWeight < spec.smoothedLeftRightWeight then
832 spec.smoothedLeftRightWeight = math.max(leftRightWeight, spec.smoothedLeftRightWeight-1/500*dt, -1)
833 else
834 spec.smoothedLeftRightWeight = math.min(leftRightWeight, spec.smoothedLeftRightWeight+1/500*dt, 1)
835 end
836
837 -- print(string.format("-- [Rideable:updateAnimation][%d][%s]\t%.6f\t%.6f\t%.6f\t%.6f\t%.6f\t%.6f\t%.6f\t%.6f\t%.6f\t%.6f", g_updateLoopIndex, tostring(self), dt, leftRightWeight, spec.smoothedLeftRightWeight, MathUtil.clamp(leftRightWeight, -1.0, 1.0), turnSpeed / spec.maxTurnSpeed, MathUtil.clamp(turnSpeed / spec.maxTurnSpeed, -1.0, 1.0), turnSpeed, speed, self.movingDirection, self.lastSpeedAcceleration * 1000 * 1000))
838
839 params.forwardVelocity.value = speed
840 params.absForwardVelocity.value = math.abs(speed)
841 params.verticalVelocity.value = speedY
842 params.yawVelocity.value = turnSpeed
843 params.absYawVelocity.value = math.abs(turnSpeed)
844 params.leftRightWeight.value = spec.smoothedLeftRightWeight
845 params.onGround.value = spec.isOnGround or spec.justSpawned
846 params.closeToGround.value = spec.isCloseToGround
847 params.inWater.value = spec.isInWater
848 params.halted.value = spec.haltTimer > 0
849 params.smoothedForwardVelocity.value = smoothedSpeed
850 params.absSmoothedForwardVelocity.value = math.abs(smoothedSpeed)
851
852 -- horse animation
853 if spec.animationPlayer ~= 0 then
854 for _, parameter in pairs(params) do
855 if parameter.type == 0 then
856 setConditionalAnimationBoolValue(spec.animationPlayer, parameter.id, parameter.value)
857 elseif parameter.type == 1 then
858 setConditionalAnimationFloatValue(spec.animationPlayer, parameter.id, parameter.value)
859 end
860 end
861 updateConditionalAnimation(spec.animationPlayer, dt)
862 -- local x,y,z = getWorldTranslation(self.rootNode)
863 -- conditionalAnimationDebugDraw(spec.animationPlayer, x,y,z)
864 end
865 local isEntered = self.getIsEntered ~= nil and self:getIsEntered()
866 local isControlled = self.getIsControlled ~= nil and self:getIsControlled()
867
868 if isEntered or isControlled then
869 -- rider animation
870 local character = self:getVehicleCharacter()
871 if character ~= nil and character.animationCharsetId ~= 0 and character.animationPlayer ~= nil then
872 for _, parameter in pairs(params) do
873 if parameter.type == 0 then
874 setConditionalAnimationBoolValue(character.animationPlayer, parameter.id, parameter.value)
875 elseif parameter.type == 1 then
876 setConditionalAnimationFloatValue(character.animationPlayer, parameter.id, parameter.value)
877 end
878 end
879 updateConditionalAnimation(character.animationPlayer, dt)
880 -- local x,y,z = getWorldTranslation(self.rootNode)
881 -- conditionalAnimationDebugDraw(character.animationPlayer, x,y,z)
882 end
883 end
884 self:updateFootsteps(dt, math.abs(speed))
885end

updateDebugValues

Description
Definition
updateDebugValues()
Code
1404function Rideable:updateDebugValues(values)
1405 local spec = self.spec_rideable
1406
1407 for k, hoofInfo in pairs(spec.hooves) do
1408 table.insert(values, {name="hoof sample " .. k, value=hoofInfo.sampleDebug})
1409 end
1410end

updateDirt

Description
Definition
updateDirt()
Code
1173function Rideable:updateDirt(dt)
1174 local spec = self.spec_rideable
1175
1176 if spec.dirtChangedCallbackFunc ~= nil and spec.inputValues.currentGait ~= Rideable.GAITTYPES.STILL then
1177 local delta = dt / (10 * 60 * 1000)
1178 local newScale = MathUtil.clamp(spec.currentDirtScale + delta, 0.0, 1.0)
1179 self:setDirtScale(newScale)
1180 spec.dirtChangedCallbackFunc(spec.dirtChangedCallbackTarget, newScale)
1181 end
1182end

updateFitness

Description
Definition
updateFitness()
Code
1186function Rideable:updateFitness(dt)
1187 local spec = self.spec_rideable
1188
1189 if spec.fitnessChangedCallbackFunc ~= nil and spec.currentSpeed ~= 0.0 then
1190 spec.fitnessChangedCallbackFunc(spec.fitnessChangedCallbackTarget, dt)
1191 end
1192end

updateFootsteps

Description
Definition
updateFootsteps()
Code
1124function Rideable:updateFootsteps(dt, speed)
1125 local spec = self.spec_rideable
1126 local epsilon = 0.001
1127
1128 if speed > epsilon then
1129 for k, hoofInfo in pairs(spec.hooves) do
1130 local posX, posY, posZ = getWorldTranslation(hoofInfo.node)
1131 spec.groundRaycastResult.object = 0
1132 spec.groundRaycastResult.y = posY - 1
1133 raycastClosest(posX, posY + Rideable.GROUND_RAYCAST_OFFSET, posZ, 0.0, -1.0, 0.0, "groundRaycastCallback", Rideable.GROUND_RAYCAST_MAXDISTANCE, self, Rideable.GROUND_RAYCAST_COLLISIONMASK)
1134
1135 local hitTerrain = spec.groundRaycastResult.object == g_currentMission.terrainRootNode
1136 local terrainY = spec.groundRaycastResult.y
1137 local onGround = ((posY - terrainY) < 0.05)
1138
1139 -- DebugUtil.drawDebugNode(hoofInfo.node, string.format("[%s] (%.6f/%.6f|%s)", getName(hoofInfo.node), posY, terrainY, tostring(((posY - terrainY) < 0.05))))
1140 if onGround and not hoofInfo.onGround then
1141 local r, g, b, _, _ = getTerrainAttributesAtWorldPos(g_currentMission.terrainRootNode, posX, posY, posZ, true, true, true, true, false)
1142 hoofInfo.onGround = true
1143 -- particles
1144 if spec.inputValues.currentGait < Rideable.GAITTYPES.CANTER then
1145 ParticleUtil.resetNumOfEmittedParticles(hoofInfo.psSlow)
1146 ParticleUtil.setEmittingState(hoofInfo.psSlow, true)
1147 setTranslation(hoofInfo.psSlow.emitterShape, posX, terrainY, posZ)
1148 setShaderParameter(hoofInfo.psSlow.shape, "psColor", r, g, b, 1, false)
1149 else
1150 ParticleUtil.resetNumOfEmittedParticles(hoofInfo.psFast)
1151 ParticleUtil.setEmittingState(hoofInfo.psFast, true)
1152 setTranslation(hoofInfo.psFast.emitterShape, posX, terrainY, posZ)
1153 setShaderParameter(hoofInfo.psFast.shape, "psColor", r, g, b, 1, false)
1154 end
1155
1156 local sample = self:getHoofSurfaceSound(posX, posY, posZ, hitTerrain)
1157 if sample ~= nil then
1158 hoofInfo.sampleDebug = string.format("%s - %s", sample.sampleName, sample.filename)
1159 g_soundManager:playSample(sample)
1160 end
1161
1162 elseif not onGround and hoofInfo.onGround then
1163 hoofInfo.onGround = false
1164 ParticleUtil.setEmittingState(hoofInfo.psSlow, false)
1165 ParticleUtil.setEmittingState(hoofInfo.psFast, false)
1166 end
1167 end
1168 end
1169end

updateInputText

Description
Definition
updateInputText()
Code
1414function Rideable:updateInputText()
1415 local spec = self.spec_rideable
1416
1417 if spec.inputValues.currentGait == Rideable.GAITTYPES.BACKWARDS then
1418 g_inputBinding:setActionEventText(spec.acceletateEventId, g_i18n:getText("action_stop"))
1419 g_inputBinding:setActionEventActive(spec.acceletateEventId, true)
1420 g_inputBinding:setActionEventTextVisibility(spec.acceletateEventId, true)
1421
1422 g_inputBinding:setActionEventActive(spec.brakeEventId, false)
1423 g_inputBinding:setActionEventTextVisibility(spec.brakeEventId, false)
1424
1425 g_inputBinding:setActionEventActive(spec.jumpEventId, false)
1426 g_inputBinding:setActionEventTextVisibility(spec.jumpEventId, false)
1427 elseif spec.inputValues.currentGait == Rideable.GAITTYPES.STILL then
1428 g_inputBinding:setActionEventText(spec.acceletateEventId, g_i18n:getText("action_walk"))
1429 g_inputBinding:setActionEventActive(spec.acceletateEventId, true)
1430 g_inputBinding:setActionEventTextVisibility(spec.acceletateEventId, true)
1431
1432 g_inputBinding:setActionEventText(spec.brakeEventId, g_i18n:getText("action_walkBackwards"))
1433 g_inputBinding:setActionEventActive(spec.brakeEventId, true)
1434 g_inputBinding:setActionEventTextVisibility(spec.brakeEventId, true)
1435
1436 g_inputBinding:setActionEventActive(spec.jumpEventId, false)
1437 g_inputBinding:setActionEventTextVisibility(spec.jumpEventId, false)
1438 elseif spec.inputValues.currentGait == Rideable.GAITTYPES.WALK then
1439 g_inputBinding:setActionEventText(spec.acceletateEventId, g_i18n:getText("action_trot"))
1440 g_inputBinding:setActionEventActive(spec.acceletateEventId, true)
1441 g_inputBinding:setActionEventTextVisibility(spec.acceletateEventId, true)
1442
1443 g_inputBinding:setActionEventText(spec.brakeEventId, g_i18n:getText("action_stop"))
1444 g_inputBinding:setActionEventActive(spec.brakeEventId, true)
1445 g_inputBinding:setActionEventTextVisibility(spec.brakeEventId, true)
1446
1447 g_inputBinding:setActionEventActive(spec.jumpEventId, false)
1448 g_inputBinding:setActionEventTextVisibility(spec.jumpEventId, false)
1449 elseif spec.inputValues.currentGait == Rideable.GAITTYPES.TROT then
1450 g_inputBinding:setActionEventText(spec.acceletateEventId, g_i18n:getText("action_canter"))
1451 g_inputBinding:setActionEventActive(spec.acceletateEventId, true)
1452 g_inputBinding:setActionEventTextVisibility(spec.acceletateEventId, true)
1453
1454 g_inputBinding:setActionEventText(spec.brakeEventId, g_i18n:getText("action_walk"))
1455 g_inputBinding:setActionEventActive(spec.brakeEventId, true)
1456 g_inputBinding:setActionEventTextVisibility(spec.brakeEventId, true)
1457
1458 g_inputBinding:setActionEventActive(spec.jumpEventId, false)
1459 g_inputBinding:setActionEventTextVisibility(spec.jumpEventId, false)
1460 elseif spec.inputValues.currentGait == Rideable.GAITTYPES.CANTER then
1461 g_inputBinding:setActionEventText(spec.acceletateEventId, g_i18n:getText("action_gallop"))
1462 g_inputBinding:setActionEventActive(spec.acceletateEventId, true)
1463 g_inputBinding:setActionEventTextVisibility(spec.acceletateEventId, true)
1464
1465 g_inputBinding:setActionEventText(spec.brakeEventId, g_i18n:getText("action_trot"))
1466 g_inputBinding:setActionEventActive(spec.brakeEventId, true)
1467 g_inputBinding:setActionEventTextVisibility(spec.brakeEventId, true)
1468
1469 g_inputBinding:setActionEventText(spec.jumpEventId, g_i18n:getText("input_JUMP"))
1470 g_inputBinding:setActionEventActive(spec.jumpEventId, true)
1471 g_inputBinding:setActionEventTextVisibility(spec.jumpEventId, true)
1472 elseif spec.inputValues.currentGait == Rideable.GAITTYPES.GALLOP then
1473 g_inputBinding:setActionEventActive(spec.acceletateEventId, false)
1474 g_inputBinding:setActionEventTextVisibility(spec.acceletateEventId, false)
1475
1476 g_inputBinding:setActionEventText(spec.brakeEventId, g_i18n:getText("action_canter"))
1477 g_inputBinding:setActionEventActive(spec.brakeEventId, true)
1478 g_inputBinding:setActionEventTextVisibility(spec.brakeEventId, true)
1479
1480 g_inputBinding:setActionEventText(spec.jumpEventId, g_i18n:getText("input_JUMP"))
1481 g_inputBinding:setActionEventActive(spec.jumpEventId, true)
1482 g_inputBinding:setActionEventTextVisibility(spec.jumpEventId, true)
1483 end
1484end

updateKinematic

Description
Update animal kinematic; if we reach max speed? we fix velocity else we add force to accelerate. If we need to break, we add a break force. At the end we add gravity force and change direction when needed.
Definition
updateKinematic(float dt)
Arguments
floatdtdelta time in ms
Code
697function Rideable:updateKinematic(dt)
698 local spec = self.spec_rideable
699 local dtInSec = dt*0.001
700
701 -- Update movement in current direction
702 local desiredSpeed = spec.topSpeeds[spec.inputValues.currentGait]
703 local maxSpeedChange = spec.maxAcceleration
704 if desiredSpeed == 0.0 then
705 maxSpeedChange = spec.maxDeceleration
706 end
707 maxSpeedChange = maxSpeedChange * dtInSec
708 if not spec.isOnGround then
709 -- reduce acceleration when in the air
710 maxSpeedChange = maxSpeedChange * 0.2
711 end
712
713 local speedChange = (desiredSpeed - spec.currentSpeed)
714 speedChange = MathUtil.clamp(speedChange, -maxSpeedChange, maxSpeedChange)
715
716 --local movement = (spec.currentSpeed + 0.5 * speedChange) * dtInSec
717 if spec.haltTimer <= 0.0 then
718 spec.currentSpeed = spec.currentSpeed + speedChange
719 else
720 spec.currentSpeed = 0.0
721 end
722
723 local movement = spec.currentSpeed * dtInSec
724
725 -- Update gravity / vertical movement
726 local gravitySpeedChange = spec.gravity * dtInSec
727 spec.currentSpeedY = spec.currentSpeedY + gravitySpeedChange
728 local movementY = spec.currentSpeedY * dtInSec
729
730 -- Update rotation
731 local slowestSpeed = spec.topSpeeds[Rideable.GAITTYPES.WALK]
732 local fastestSpeed = spec.topSpeeds[Rideable.GAITTYPES.MAX]
733
734 local maxTurnSpeedChange = (MathUtil.clamp((fastestSpeed - spec.currentSpeed) / (fastestSpeed - slowestSpeed), 0, 1) * 0.4 + 0.8) -- Use smaller changes when walking slowly (between 0.8 and 1.2 rad/s^2)
735 maxTurnSpeedChange = maxTurnSpeedChange * dtInSec
736 if not spec.isOnGround then
737 -- reduce turn acceleration when in the air
738 maxTurnSpeedChange = maxTurnSpeedChange * 0.25
739 end
740
741 if self.isServer then
742 if not self:getIsEntered() and not self:getIsControlled() and spec.inputValues.axisSteer ~= 0.0 then
743 spec.inputValues.axisSteer = 0.0
744 end
745 end
746
747 local desiredTurnSpeed = spec.maxTurnSpeed * spec.inputValues.axisSteer
748 local turnSpeedChange = (desiredTurnSpeed - spec.currentTurnSpeed)
749 turnSpeedChange = MathUtil.clamp(turnSpeedChange, -maxTurnSpeedChange, maxTurnSpeedChange)
750 spec.currentTurnSpeed = spec.currentTurnSpeed + turnSpeedChange
751 spec.currentTurnAngle = spec.currentTurnAngle + spec.currentTurnSpeed * dtInSec * (movement >= 0 and 1 or -1)
752
753 local movementX, movementZ = math.sin(spec.currentTurnAngle) * movement, math.cos(spec.currentTurnAngle) * movement
754 -- print(string.format("-- [Rideable:updateKinematic][%d]\t%.6f\t%.6f\t%.6f\t%d", g_updateLoopIndex, dt, spec.currentSpeed, movement, getPhysicsUpdateIndex()))
755 self:moveCCT(movementX, movementY, movementZ, true)
756
757 table.insert(spec.cctMoveQueue, {physicsIndex = getPhysicsUpdateIndex(), moveX = movementX, moveY = movementY, moveZ = movementZ, dt = dt})
758end

updateSound

Description
Definition
updateSound()
Code
889function Rideable:updateSound(dt)
890 local spec = self.spec_rideable
891
892 if spec.horseBreathSoundsEffort ~= nil and spec.horseBreathSoundsNoEffort ~= nil and spec.isOnGround then
893 spec.currentBreathTimer = spec.currentBreathTimer - dt
894 spec.currentBreathTimer = math.max(spec.currentBreathTimer, 0.0)
895
896 if spec.currentBreathTimer == 0.0 then
897 if spec.inputValues.currentGait == Rideable.GAITTYPES.GALLOP then
898 g_soundManager:playSample(spec.horseBreathSoundsEffort)
899 spec.currentBreathTimer = spec.horseBreathIntervalEffort
900 else
901 g_soundManager:playSample(spec.horseBreathSoundsNoEffort)
902 if spec.inputValues.currentGait == Rideable.GAITTYPES.STILL then
903 spec.currentBreathTimer = spec.horseBreathMinIntervalIdle + (math.random() * (spec.horseBreathMaxIntervalIdle - spec.horseBreathMinIntervalIdle))
904 else
905 spec.currentBreathTimer = spec.horseBreathIntervalNoEffort
906 end
907 end
908 end
909 end
910end