LUADOC - Farming Simulator 22

Script v1_7_1_0

Engine v1_7_1_0

Foundation Reference

Locomotive

Description
Specialization for locomotives (railroad vehicle)
Functions

alignToSplineTime

Description
Definition
alignToSplineTime()
Code
567function Locomotive:alignToSplineTime(superFunc, spline, yOffset, tFront)
568 local retValue = superFunc(self, spline, yOffset, tFront)
569
570 if retValue ~= nil then
571 local spec = self.spec_locomotive
572 if spec.powerArm ~= nil and spec.electricitySpline ~= nil then
573 retValue = SplineUtil.getValidSplineTime(retValue)
574 local _
575 local x, y, z = getWorldTranslation(spec.powerArm)
576 x, y, z, _ = getLocalClosestSplinePosition(spec.electricitySpline, retValue, spec.electricitySplineSearchTime, x, y, z, 0.01)
577
578 _, y, _ = worldToLocal(getParent(spec.powerArm), x, y, z)
579 x, _, z = getTranslation(spec.powerArm)
580 setTranslation(spec.powerArm, x, y, z)
581 if spec.powerArm ~= nil then
582 self:setMovingToolDirty(spec.powerArm)
583 end
584
585-- local x, y, z = getSplinePosition(spec.electricitySpline, newTime)
586-- local dx, dy, dz = getSplineDirection(spec.electricitySpline, newTime)
587-- log(string.format("%.4f %.4f %.4f %.4f", retValue, electricityTime, dif, newTime))
588-- DebugUtil.drawDebugGizmoAtWorldPos(x, y, z, dx, dy, dz, 0, 1, 0, "E "..tFront.." " ..electricityTime.." " ..newTime)
589
590 end
591 end
592
593 if not self.isServer then
594 self:updateMapHotspot()
595 end
596
597 return retValue
598end

getAreSurfaceSoundsActive

Description
Definition
getAreSurfaceSoundsActive()
Code
247function Locomotive:getAreSurfaceSoundsActive(superFunc)
248 return self:getLastSpeed() > 0.1
249end

getBrakeAcceleration

Description
Definition
getBrakeAcceleration()
Code
429function Locomotive.getBrakeAcceleration(self)
430 local spec = self.spec_locomotive
431 local downhillForce = self:getDownhillForce()
432 local maxBrakeForce = self.serverMass * 9.81 * 0.18
433 local brakeForce
434
435 if math.abs(spec.speed) < 0.3 or not self:getIsControlled() then
436 brakeForce = maxBrakeForce
437 else
438 brakeForce = maxBrakeForce * 0.05
439 end
440
441 brakeForce = brakeForce * MathUtil.sign(spec.speed)
442
443 return (1/self.serverMass) * (-brakeForce - downhillForce)
444end

getCanBeReset

Description
Definition
getCanBeReset()
Code
602function Locomotive:getCanBeReset(superFunc)
603 return false
604end

getDistanceToRequestedPosition

Description
Definition
getDistanceToRequestedPosition()
Code
314function Locomotive:getDistanceToRequestedPosition()
315 local spec = self.spec_locomotive
316 if spec.state == Locomotive.STATE_REQUESTED_POSITION_BRAKING or spec.state == Locomotive.STATE_REQUESTED_POSITION then
317 local currentPosition = self:getCurrentSplinePosition()
318 local requestedPosition = spec.requestedSplinePosition
319
320 local distanceToGo = math.abs(requestedPosition - currentPosition)
321 if spec.state == Locomotive.STATE_REQUESTED_POSITION_BRAKING and distanceToGo > 0.5 then
322 -- if we brake a bit late and go over the requested position
323 return 0
324 end
325
326 return distanceToGo * self.trainSystem:getSplineLength()
327 end
328
329 return 0
330end

getDownhillForce

Description
Definition
getDownhillForce()
Code
420function Locomotive:getDownhillForce()
421 local dirX, dirY, dirZ = localDirectionToWorld(self.rootNode, 0,0,1)
422 local angleX = math.acos(dirY / MathUtil.vector3Length(dirX, dirY, dirZ)) - 0.5*math.pi
423
424 return self.serverMass * 9.81 * math.sin(-angleX)
425end

getFullName

Description
Definition
getFullName()
Code
240function Locomotive:getFullName(superFunc)
241 local storeItem = g_storeManager:getItemByXMLFilename(self.configFileName)
242 return storeItem.name
243end

getIsEnterable

Description
Definition
getIsEnterable()
Code
260function Locomotive:getIsEnterable(superFunc)
261 if not superFunc(self) then
262 return false
263 end
264
265 if self.trainSystem ~= nil and not self.trainSystem:getIsTrainInDriveableRange() then
266 return false
267 end
268
269 local spec = self.spec_locomotive
270 return spec.state == Locomotive.STATE_MANUAL_TRAVEL_ACTIVE or spec.state == Locomotive.STATE_MANUAL_TRAVEL_INACTIVE
271end

getIsMapHotspotVisible

Description
Definition
getIsMapHotspotVisible()
Code
275function Locomotive:getIsMapHotspotVisible(superFunc)
276 if not superFunc(self) then
277 return false
278 end
279
280 if self.trainSystem ~= nil and not self.trainSystem:getIsTrainInDriveableRange() then
281 return false
282 end
283
284 local x, _, z = getWorldTranslation(self.rootNode)
285 if math.abs(x) > g_currentMission.terrainSize * 0.5 or math.abs(z) > g_currentMission.terrainSize * 0.5 then
286 return false
287 end
288
289 return true
290end

getIsMotorStarted

Description
Definition
getIsMotorStarted()
Code
410function Locomotive:getIsMotorStarted(superFunc)
411 local spec = self.spec_locomotive
412 return superFunc(self)
413 or spec.state == Locomotive.STATE_AUTOMATIC_TRAVEL_ACTIVE
414 or spec.state == Locomotive.STATE_REQUESTED_POSITION
415 or spec.state == Locomotive.STATE_REQUESTED_POSITION_BRAKING
416end

getIsReadyForAutomatedTrainTravel

Description
Definition
getIsReadyForAutomatedTrainTravel()
Code
400function Locomotive:getIsReadyForAutomatedTrainTravel(superFunc)
401 if self:getIsControlled() then
402 return false
403 end
404
405 return superFunc(self)
406end

getTraveledDistanceStatsActive

Description
Definition
getTraveledDistanceStatsActive()
Code
253function Locomotive:getTraveledDistanceStatsActive(superFunc)
254 local spec = self.spec_locomotive
255 return spec.state == Locomotive.STATE_MANUAL_TRAVEL_ACTIVE
256end

initSpecialization

Description
Definition
initSpecialization()
Code
36function Locomotive.initSpecialization()
37 local schema = Vehicle.xmlSchema
38 schema:setXMLSpecializationType("Locomotive")
39
40 schema:register(XMLValueType.NODE_INDEX, "vehicle.locomotive.powerArm#node", "Power arm node")
41
42 schema:setXMLSpecializationType()
43end

notifyPlayerFarmChanged

Description
Definition
notifyPlayerFarmChanged()
Code
360function Locomotive:notifyPlayerFarmChanged()
361 if self.trainSystem ~= nil then
362 self:setIsTabbable(self.trainSystem.isRented and g_currentMission.player.farmId == self.trainSystem.rentFarmId)
363 end
364end

onDelete

Description
Definition
onDelete()
Code
123function Locomotive:onDelete()
124 g_messageCenter:unsubscribeAll(self)
125end

onEnterVehicle

Description
Definition
onEnterVehicle()
Code
384function Locomotive:onEnterVehicle()
385 local spec = self.spec_locomotive
386 spec.requestedSplinePosition = nil
387 spec.automaticTravelStartTime = nil
388
389 if not g_currentMission.missionInfo.automaticMotorStartEnabled then
390 if spec.state == Locomotive.STATE_AUTOMATIC_TRAVEL_ACTIVE or spec.state == Locomotive.STATE_REQUESTED_POSITION or spec.state == Locomotive.STATE_REQUESTED_POSITION_BRAKING then
391 self:startMotor(true)
392 end
393 end
394
395 self:setLocomotiveState(Locomotive.STATE_MANUAL_TRAVEL_ACTIVE)
396end

onLeaveVehicle

Description
Definition
onLeaveVehicle()
Code
368function Locomotive:onLeaveVehicle()
369 local spec = self.spec_locomotive
370 if spec.state ~= Locomotive.STATE_AUTOMATIC_TRAVEL_ACTIVE then
371 if self:getIsReadyForAutomatedTrainTravel() then
372 spec.automaticTravelStartTime = g_time + Locomotive.AUTOMATIC_DRIVE_DELAY
373 end
374
375 self:setLocomotiveState(Locomotive.STATE_MANUAL_TRAVEL_INACTIVE)
376 self:raiseActive()
377
378 spec.requestedSplinePosition = nil
379 end
380end

onLoad

Description
Called on loading
Definition
onLoad(table savegame)
Arguments
tablesavegamesavegame
Code
94function Locomotive:onLoad(savegame)
95 local spec = self.spec_locomotive
96
97 self.serverMass = 1 -- set serverMass ~= 0 to prevent dib by zero issues after load
98
99 spec.powerArm = self.xmlFile:getValue("vehicle.locomotive.powerArm#node", nil, self.components, self.i3dMappings)
100 spec.electricitySpline = nil
101
102 spec.lastVirtualRpm = self:getMotor():getMinRpm()
103 spec.speed = 0
104 spec.lastAcceleration = 0
105 spec.nextMovingDirection = 0
106 spec.sellingDirection = 1
107
108 spec.startBrakeDistance = 0
109 spec.startBrakeSpeed = 0
110
111 self:setLocomotiveState(Locomotive.STATE_NONE)
112
113 spec.motor = self:getMotor()
114
115 spec.doStartCheck = true
116
117 g_messageCenter:subscribe(MessageType.PLAYER_FARM_CHANGED, self.notifyPlayerFarmChanged, self)
118 g_messageCenter:subscribe(MessageType.PLAYER_CREATED, self.notifyPlayerFarmChanged, self)
119end

onReadStream

Description
Called on client side on join
Definition
onReadStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
131function Locomotive:onReadStream(streamId, connection)
132 self.spec_locomotive.state = streamReadUIntN(streamId, Locomotive.NUM_BITS_STATE)
133end

onUpdate

Description
Definition
onUpdate()
Code
145function Locomotive:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
146 local spec = self.spec_locomotive
147
148 if spec.doStartCheck then
149 if self.trainSystem ~= nil then
150 if not self.trainSystem:getIsRented() then
151 self:startAutomatedTrainTravel()
152 else
153 self:setLocomotiveState(Locomotive.STATE_MANUAL_TRAVEL_ACTIVE)
154 end
155
156 self:raiseActive()
157 spec.doStartCheck = false
158 end
159 end
160
161 -- update motor as long as locomotive is still moving but no player has entered
162 if self.isServer then
163 if spec.state == Locomotive.STATE_AUTOMATIC_TRAVEL_ACTIVE then
164 self:raiseActive()
165 self:updateVehiclePhysics(1, 0, 0, dt)
166 SpecializationUtil.raiseEvent(self, "onAutomatedTrainTravelActive", dt)
167 elseif spec.state == Locomotive.STATE_REQUESTED_POSITION then
168 if spec.requestedSplinePosition ~= nil then
169 local splineLength = self.trainSystem:getSplineLength()
170 local currentPosition = self:getCurrentSplinePosition()
171 local requestedPosition = spec.requestedSplinePosition
172
173 local targetDirection = MathUtil.sign(requestedPosition-currentPosition)
174 local brakeAcceleration = Locomotive.getBrakeAcceleration(self)
175 local brakeDistance = math.abs((spec.speed^2)/(2*brakeAcceleration))
176 local brakePoint = (requestedPosition - (brakeDistance / splineLength) * targetDirection) % 1
177 local pendingDirectionChange = not (targetDirection == self.movingDirection or self.movingDirection == 0)
178 if not pendingDirectionChange and ((targetDirection >= 0 and (currentPosition > brakePoint and currentPosition < brakePoint + 0.5))
179 or (targetDirection < 0 and (currentPosition < brakePoint and currentPosition > brakePoint - 0.5))) then
180 self:setLocomotiveState(Locomotive.STATE_REQUESTED_POSITION_BRAKING)
181
182 spec.startBrakeDistance = brakeDistance
183 spec.startBrakeSpeed = spec.speed
184 else
185 self:updateVehiclePhysics(targetDirection, 0, 0, dt)
186 end
187 self:raiseActive()
188 end
189 elseif spec.state == Locomotive.STATE_REQUESTED_POSITION_BRAKING then
190 -- if we detect that we could stop way earlier (e.g. due to changing slope) we release the brake again
191 local brakeAcceleration = Locomotive.getBrakeAcceleration(self)
192 local brakeDistance = math.abs((spec.startBrakeSpeed^2)/(2*brakeAcceleration))
193 if brakeDistance < spec.startBrakeDistance - 10 then
194 self:setLocomotiveState(Locomotive.STATE_REQUESTED_POSITION)
195 end
196
197 if self.movingDirection > 0 then
198 self:updateVehiclePhysics(-1, 0, 0, dt)
199 else
200 self:updateVehiclePhysics(1, 0, 0, dt)
201 end
202
203 self:raiseActive()
204 if spec.speed == 0 then
205 self:setLocomotiveState(Locomotive.STATE_MANUAL_TRAVEL_ACTIVE)
206
207 self:stopMotor()
208 end
209 elseif spec.state == Locomotive.STATE_MANUAL_TRAVEL_INACTIVE then
210 if self.movingDirection > 0 then
211 self:updateVehiclePhysics(-1, 0, 0, dt)
212 else
213 self:updateVehiclePhysics(1, 0, 0, dt)
214 end
215 self:raiseActive()
216 end
217 end
218end

onWriteStream

Description
Called on server side on join
Definition
onWriteStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
139function Locomotive:onWriteStream(streamId, connection)
140 streamWriteUIntN(streamId, self.spec_locomotive.state, Locomotive.NUM_BITS_STATE)
141end

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
30function Locomotive.prerequisitesPresent(specializations)
31 return SpecializationUtil.hasSpecialization(SplineVehicle, specializations) and SpecializationUtil.hasSpecialization(Drivable, specializations)
32end

registerEventListeners

Description
Definition
registerEventListeners()
Code
80function Locomotive.registerEventListeners(vehicleType)
81 SpecializationUtil.registerEventListener(vehicleType, "onLoad", Locomotive)
82 SpecializationUtil.registerEventListener(vehicleType, "onDelete", Locomotive)
83 SpecializationUtil.registerEventListener(vehicleType, "onReadStream", Locomotive)
84 SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", Locomotive)
85 SpecializationUtil.registerEventListener(vehicleType, "onUpdate", Locomotive)
86 SpecializationUtil.registerEventListener(vehicleType, "onLeaveVehicle", Locomotive)
87 SpecializationUtil.registerEventListener(vehicleType, "onEnterVehicle", Locomotive)
88end

registerEvents

Description
Definition
registerEvents()
Code
47function Locomotive.registerEvents(vehicleType)
48 SpecializationUtil.registerEvent(vehicleType, "onAutomatedTrainTravelActive")
49end

registerFunctions

Description
Definition
registerFunctions()
Code
53function Locomotive.registerFunctions(vehicleType)
54 SpecializationUtil.registerFunction(vehicleType, "getDownhillForce", Locomotive.getDownhillForce)
55 SpecializationUtil.registerFunction(vehicleType, "setRequestedSplinePosition", Locomotive.setRequestedSplinePosition)
56 SpecializationUtil.registerFunction(vehicleType, "getDistanceToRequestedPosition", Locomotive.getDistanceToRequestedPosition)
57 SpecializationUtil.registerFunction(vehicleType, "setLocomotiveState", Locomotive.setLocomotiveState)
58 SpecializationUtil.registerFunction(vehicleType, "startAutomatedTrainTravel", Locomotive.startAutomatedTrainTravel)
59 SpecializationUtil.registerFunction(vehicleType, "notifyPlayerFarmChanged", Locomotive.notifyPlayerFarmChanged)
60end

registerOverwrittenFunctions

Description
Definition
registerOverwrittenFunctions()
Code
64function Locomotive.registerOverwrittenFunctions(vehicleType)
65 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsMotorStarted", Locomotive.getIsMotorStarted)
66 SpecializationUtil.registerOverwrittenFunction(vehicleType, "updateVehiclePhysics", Locomotive.updateVehiclePhysics)
67 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsReadyForAutomatedTrainTravel", Locomotive.getIsReadyForAutomatedTrainTravel)
68 SpecializationUtil.registerOverwrittenFunction(vehicleType, "alignToSplineTime", Locomotive.alignToSplineTime)
69 SpecializationUtil.registerOverwrittenFunction(vehicleType, "setTrainSystem", Locomotive.setTrainSystem)
70 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getFullName", Locomotive.getFullName)
71 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getAreSurfaceSoundsActive", Locomotive.getAreSurfaceSoundsActive)
72 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getTraveledDistanceStatsActive", Locomotive.getTraveledDistanceStatsActive)
73 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsEnterable", Locomotive.getIsEnterable)
74 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsMapHotspotVisible", Locomotive.getIsMapHotspotVisible)
75 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getCanBeReset", Locomotive.getCanBeReset)
76end

setLocomotiveState

Description
Definition
setLocomotiveState()
Code
334function Locomotive:setLocomotiveState(state, noEventSend)
335 local spec = self.spec_locomotive
336 spec.state = state
337
338 if state == Locomotive.STATE_AUTOMATIC_TRAVEL_ACTIVE then
339 if self.setRandomVehicleCharacter ~= nil then
340 self:setRandomVehicleCharacter()
341 end
342 elseif state == Locomotive.STATE_MANUAL_TRAVEL_ACTIVE then
343 self:restoreVehicleCharacter()
344 end
345
346 if g_server ~= nil and not noEventSend then
347 g_server:broadcastEvent(LocomotiveStateEvent.new(self, state), nil, nil, self)
348 end
349end

setRequestedSplinePosition

Description
Definition
setRequestedSplinePosition()
Code
294function Locomotive:setRequestedSplinePosition(splinePosition, noEventSend)
295 local spec = self.spec_locomotive
296 spec.requestedSplinePosition = splinePosition
297 self:setLocomotiveState(Locomotive.STATE_REQUESTED_POSITION, true)
298
299 local currentPosition = self:getCurrentSplinePosition()
300 local requestedPosition = spec.requestedSplinePosition
301 if currentPosition > spec.requestedSplinePosition then
302 if math.abs(currentPosition - (requestedPosition + 1)) < math.abs(currentPosition - requestedPosition) then
303 spec.requestedSplinePosition = requestedPosition + 1
304 end
305 end
306
307 if self.isServer then
308 self:startMotor()
309 end
310end

setTrainSystem

Description
Definition
setTrainSystem()
Code
222function Locomotive:setTrainSystem(superFunc, trainSystem)
223 superFunc(self, trainSystem)
224
225 local spec = self.spec_locomotive
226 if spec.powerArm ~= nil then
227 local spline = trainSystem:getElectricitySpline()
228 if spline ~= nil then
229 local electricitySplineLength = trainSystem:getElectricitySplineLength()
230 local splineLength = trainSystem:getSplineLength()
231 spec.splineDiff = math.abs(electricitySplineLength - splineLength)
232 spec.electricitySplineSearchTime = spec.splineDiff * 5 / electricitySplineLength
233 spec.electricitySpline = spline
234 end
235 end
236end

startAutomatedTrainTravel

Description
Definition
startAutomatedTrainTravel()
Code
353function Locomotive:startAutomatedTrainTravel()
354 self:setLocomotiveState(Locomotive.STATE_AUTOMATIC_TRAVEL_ACTIVE)
355 self:startMotor()
356end

updateVehiclePhysics

Description
Definition
updateVehiclePhysics()
Code
448function Locomotive:updateVehiclePhysics(superFunc, axisForward, axisSide, doHandbrake, dt)
449 local spec = self.spec_locomotive
450 local specDrivable = self.spec_drivable
451
452 axisForward = axisForward * spec.sellingDirection
453
454 local acceleration = superFunc(self, axisForward, axisSide, doHandbrake, dt)
455
456 local interpDt = g_physicsDt
457 if g_server == nil then
458 -- on clients, we interpolate the vehicles with g_physicsDtUnclamped, thus we need to use the same for camera interpolation
459 interpDt = g_physicsDtUnclamped
460 end
461
462 -- assuming:
463 -- totalMass: mass,
464 -- P(v): tractive effort of locomotive
465 -- Q(v): drag of train (dismissed)
466 -- B: brake force
467 -- g: gravity
468 -- alpha: inclination angle
469 --
470 -- totalMass*a = P(v) - Q(v) - B - totalMass*g*sin(alpha)
471 -- a = 1/totalMass * [ (P(v) - Q(v) - B - totalMass*g*sin(alpha) ]
472
473 local tractiveEffort = 300000
474 local maxBrakeForce = self.serverMass * 9.81 * 0.18
475 local downhillForce = self:getDownhillForce()
476 tractiveEffort = math.min(tractiveEffort, maxBrakeForce)
477
478 if self:getIsMotorStarted() and self:getMotorStartTime() <= g_currentMission.time then
479 local reverserDirection = specDrivable == nil and 1 or specDrivable.reverserDirection
480 if self:getCruiseControlState() ~= Drivable.CRUISECONTROL_STATE_OFF then
481 local cruiseControlSpeed = self:getCruiseControlSpeed() / 3.6
482 if spec.speed < reverserDirection * cruiseControlSpeed then
483 acceleration = 1
484 elseif spec.speed > reverserDirection * cruiseControlSpeed then
485 acceleration = -1
486 end
487 end
488 else
489 tractiveEffort = maxBrakeForce
490 end
491
492 if math.abs(acceleration) < 0.001 then
493 local a = Locomotive.getBrakeAcceleration(self)
494
495 if spec.speed > 0 then
496 spec.speed = math.max(0, spec.speed + a * dt/1000)
497 elseif spec.speed < 0 then
498 spec.speed = math.min(0, spec.speed + a * dt/1000)
499 else
500 -- move train if track is too steep ???
501 if maxBrakeForce < math.abs(downhillForce) then
502 spec.speed = spec.speed + a * dt/1000
503 end
504 end
505
506 if spec.speed == 0 then
507 spec.hasStopped = true
508 else
509 spec.hasStopped = false
510 end
511 else
512 if math.abs(spec.speed) > 0.1 then
513 spec.hasStopped = false
514 elseif math.abs(spec.speed) == 0 then
515 spec.hasStopped = true
516 end
517 if spec.hasStopped == nil or (spec.hasStopped and math.abs(acceleration) > 0.01) then
518 spec.nextMovingDirection = MathUtil.sign(acceleration)
519 end
520
521 local a = 0
522 local brakeForce
523 if spec.nextMovingDirection == nil or (spec.nextMovingDirection * acceleration) > 0 then
524 tractiveEffort = acceleration * tractiveEffort
525 brakeForce = 0
526 a = (1/self.serverMass) * ( tractiveEffort - brakeForce - downhillForce )
527 else
528 tractiveEffort = 0
529 brakeForce = MathUtil.sign(spec.speed) * math.abs(acceleration) * maxBrakeForce
530 if math.abs(spec.speed) < 0.1 then
531 spec.speed = 0
532 else
533 a = (1/self.serverMass) * ( tractiveEffort - brakeForce - downhillForce )
534 end
535 end
536
537 spec.speed = spec.speed + a * interpDt/1000
538 end
539
540 local motor = spec.motor
541 if spec.speed > 0 then
542 spec.speed = math.min(spec.speed, motor.maxForwardSpeed)
543 elseif spec.speed < 0 then
544 spec.speed = math.max(spec.speed, -motor.maxBackwardSpeed)
545 end
546
547 if spec.speed ~= 0 then
548 self.trainSystem:updateTrainPositionByLocomotiveSpeed(interpDt, spec.speed)
549 end
550
551 local minRpm = motor.minRpm
552 local maxRpm = motor.maxRpm
553 -- fake rpm for indoorHud
554 if spec.lastAcceleration * spec.nextMovingDirection > 0 then
555 spec.lastVirtualRpm = math.min(maxRpm, spec.lastVirtualRpm + (0.0005 * dt * (maxRpm - minRpm)))
556 else
557 spec.lastVirtualRpm = math.max(minRpm, spec.lastVirtualRpm - (0.001 * dt * (maxRpm - minRpm)))
558 end
559
560 motor:setEqualizedMotorRpm(spec.lastVirtualRpm)
561
562 spec.lastAcceleration = acceleration
563end