Script v1.7.1.0
- AI
- Animals
- Contracts
- Debug
- Economy
- Effects
- Events
- Farms
- GUI
- Handtools
- I3d
- Materials
- Misc
- Objects
- Placeables
- Player
- Shop
- Sounds
- Specializations
- AIConveyorBelt
- AIImplement
- AIVehicle
- AnimatedVehicle
- ArticulatedAxis
- Attachable
- AttacherJointControl
- AttacherJoints
- BaleGrab
- BaleLoader
- Baler
- BaleWrapper
- BaseMaterial
- BunkerSiloCompacter
- BunkerSiloInteractor
- BuyableBale
- CCTDrivable
- Combine
- ConnectionHoses
- ConveyorBelt
- Cover
- CrabSteering
- Crawlers
- Cultivator
- Cutter
- Cylindered
- CylinderedFoldable
- Dashboard
- Dischargeable
- Drivable
- DynamicallyLoadedParts
- DynamicMountAttacher
- Enterable
- FertilizingCultivator
- FertilizingSowingMachine
- FillTriggerVehicle
- FillUnit
- FillVolume
- Foldable
- FoliageBending
- ForageWagon
- FrontloaderAttacher
- FruitPreparer
- GroundAdjustedNodes
- GroundReference
- Honk
- HookLiftContainer
- HookLiftTrailer
- IKChains
- JigglingParts
- Leveler
- Lights
- LivestockTrailer
- Locomotive
- LogGrab
- ManureBarrel
- MixerWagon
- Motorized
- Mountable
- Mower
- Pickup
- Pipe
- Plow
- PowerConsumer
- PowerTakeOffs
- RandomlyMovingParts
- ReceivingHopper
- ReverseDriving
- Rideable
- RidgeMarker
- Roller
- Ropes
- SemiTrailerFront
- Shovel
- SlopeCompensation
- SmartAttach
- SowingMachine
- SpeedRotatingParts
- SplineVehicle
- Sprayer
- StrawBlower
- StumpCutter
- Suspensions
- Tedder
- TensionBeltObject
- TensionBelts
- TipOccluder
- Trailer
- TreePlanter
- TreeSaw
- TurnOnVehicle
- Washable
- WaterTrailer
- Wearable
- Weeder
- Wheels
- Windrower
- Wipers
- WoodCrusher
- WoodHarvester
- WorkArea
- WorkMode
- WorkParticles
- Triggers
- Utils
- Vehicles
- Weather
Engine v1.7.1.0
- AI
- Animation
- Camera
- Entity
- Fillplanes
- General
- I3D
- Input
- Lighting
- Math
- Network
- Node
- Overlays
- Particle System
- Physics
- Rendering
- Scenegraph
- Shape
- Sound
- Spline
- String
- Terrain Detail
- Text Rendering
- Tire Track
- XML
- general
Foundation Reference
Locomotive
DescriptionSpecialization for locomotives (railroad vehicle)Functions
- alignToSplineTime
- getAreSurfaceSoundsActive
- getBrakeAcceleration
- getDownhillForce
- getFullName
- getIsMotorStarted
- getIsReadyForAutomatedTrainTravel
- getTravedDistanceStatsActive
- onEnterVehicle
- onLeaveVehicle
- onLoad
- onUpdate
- onUpdateTick
- prerequisitesPresent
- registerEventListeners
- registerEvents
- registerFunctions
- registerOverwrittenFunctions
- setLocomotiveState
- setRequestedSplinePosition
- setTrainSystem
- updateVehiclePhysics
alignToSplineTime
DescriptionDefinitionalignToSplineTime()Code
434 | function Locomotive:alignToSplineTime(superFunc, spline, yOffset, tFront) |
435 | local retValue = superFunc(self, spline, yOffset, tFront) |
436 | |
437 | if retValue ~= nil then |
438 | local spec = self.spec_locomotive |
439 | if spec.powerArm ~= nil and spec.electricitySpline ~= nil then |
440 | retValue = SplineUtil.getValidSplineTime(retValue) |
441 | local dif = retValue - spec.lastSplineTime |
442 | local electricityTime = spec.lastElectricitySplineTime + dif |
443 | local x, y, z = getWorldTranslation(spec.powerArm) |
444 | local x,y,z, newTime = getLocalClosestSplinePosition(spec.electricitySpline, electricityTime, spec.electricitySplineSearchTime, x, y, z, 0.01) --SplineUtil.getSplineTimeAtWorldPos(spec.electricitySpline, electricityTime, x, z, spec.splineDiff * 4, 30) |
445 | |
446 | --local x, y, z = getSplinePosition(spec.electricitySpline, newTime) |
447 | --local dx, dy, dz = getSplineDirection(spec.electricitySpline, newTime) |
448 | -- log(string.format("%.4f %.4f %.4f %.4f", retValue, electricityTime, dif, newTime)) |
449 | -- DebugUtil.drawDebugGizmoAtWorldPos(x,y,z, dx, dy, dz, 0, 1, 0, "E "..tFront.." " ..electricityTime.." " ..newTime) |
450 | |
451 | _, y, _ = worldToLocal(getParent(spec.powerArm), x, y, z) |
452 | local x, _, z = getTranslation(spec.powerArm) |
453 | setTranslation(spec.powerArm, x, y, z) |
454 | if spec.powerArm ~= nil then |
455 | self:setMovingToolDirty(spec.powerArm) |
456 | end |
457 | |
458 | spec.lastElectricitySplineTime = newTime |
459 | spec.lastSplineTime = retValue |
460 | end |
461 | end |
462 | |
463 | return retValue |
464 | end |
getAreSurfaceSoundsActive
DescriptionDefinitiongetAreSurfaceSoundsActive()Code
205 | function Locomotive:getAreSurfaceSoundsActive(superFunc) |
206 | return self:getLastSpeed() > 0.1 |
207 | end |
getBrakeAcceleration
DescriptionDefinitiongetBrakeAcceleration()Code
297 | function Locomotive.getBrakeAcceleration(self) |
298 | local spec = self.spec_locomotive |
299 | local downhillForce = spec:getDownhillForce() |
300 | local totalMass = self:getTotalMass(false) |
301 | local maxBrakeForce = totalMass * 9.81 * 0.18 |
302 | local brakeForce = maxBrakeForce |
303 | |
304 | if math.abs(spec.speed) < 0.3 or not self:getIsControlled() then |
305 | brakeForce = maxBrakeForce |
306 | else |
307 | brakeForce = maxBrakeForce * 0.05 |
308 | end |
309 | |
310 | brakeForce = brakeForce * MathUtil.sign(spec.speed) |
311 | |
312 | return (1/totalMass) * (-brakeForce - downhillForce) |
313 | end |
getDownhillForce
DescriptionDefinitiongetDownhillForce()Code
287 | function Locomotive:getDownhillForce() |
288 | local mass = self:getTotalMass(false) |
289 | local dirX, dirY, dirZ = localDirectionToWorld(self.rootNode, 0,0,1) |
290 | local angleX = math.acos(dirY / MathUtil.vector3Length(dirX, dirY, dirZ)) - 0.5*math.pi |
291 | |
292 | return mass * 9.81 * math.sin(-angleX) |
293 | end |
getFullName
DescriptionDefinitiongetFullName()Code
198 | function Locomotive:getFullName(superFunc) |
199 | local storeItem = g_storeManager:getItemByXMLFilename(self.configFileName) |
200 | return storeItem.name |
201 | end |
getIsMotorStarted
DescriptionDefinitiongetIsMotorStarted()Code
277 | function Locomotive:getIsMotorStarted(superFunc) |
278 | local spec = self.spec_locomotive |
279 | return superFunc(self) |
280 | or spec.state == Locomotive.STATE_AUTOMATIC_TRAVEL_ACTIVE |
281 | or spec.state == Locomotive.STATE_REQUESTED_POSITION |
282 | or spec.state == Locomotive.STATE_REQUESTED_POSITION_BRAKING |
283 | end |
getIsReadyForAutomatedTrainTravel
DescriptionDefinitiongetIsReadyForAutomatedTrainTravel()Code
267 | function Locomotive:getIsReadyForAutomatedTrainTravel(superFunc) |
268 | if self:getIsControlled() then |
269 | return false |
270 | end |
271 | |
272 | return superFunc(self) |
273 | end |
getTravedDistanceStatsActive
DescriptionDefinitiongetTravedDistanceStatsActive()Code
211 | function Locomotive:getTravedDistanceStatsActive(superFunc) |
212 | return self.state == Locomotive.STATE_MANUAL_TRAVEL_ACTIVE |
213 | end |
onEnterVehicle
DescriptionDefinitiononEnterVehicle()Code
251 | function Locomotive:onEnterVehicle() |
252 | local spec = self.spec_locomotive |
253 | spec.requestedSplinePosition = nil |
254 | spec.automaticTravelStartTime = nil |
255 | |
256 | if not g_currentMission.missionInfo.automaticMotorStartEnabled then |
257 | if spec.state == Locomotive.STATE_AUTOMATIC_TRAVEL_ACTIVE or spec.state == Locomotive.STATE_REQUESTED_POSITION or spec.state == Locomotive.STATE_REQUESTED_POSITION_BRAKING then |
258 | self:startMotor(true) |
259 | end |
260 | end |
261 | |
262 | self:setLocomotiveState(Locomotive.STATE_MANUAL_TRAVEL_ACTIVE) |
263 | end |
onLeaveVehicle
DescriptionDefinitiononLeaveVehicle()Code
237 | function Locomotive:onLeaveVehicle() |
238 | local spec = self.spec_locomotive |
239 | if self:getIsReadyForAutomatedTrainTravel() then |
240 | spec.automaticTravelStartTime = g_time + Locomotive.AUTOMATIC_DRIVE_DELAY |
241 | end |
242 | |
243 | self:setLocomotiveState(Locomotive.STATE_MANUAL_TRAVEL_INACTIVE) |
244 | self:raiseActive() |
245 | |
246 | spec.requestedSplinePosition = nil |
247 | end |
onLoad
DescriptionCalled on loadingDefinition
onLoad(table savegame)Arguments
table | savegame | savegame |
74 | function Locomotive:onLoad(savegame) |
75 | local spec = self.spec_locomotive |
76 | |
77 | spec.powerArm = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.locomotive.powerArm#node"), self.i3dMappings) |
78 | spec.lastElectricitySplineTime = 0 |
79 | spec.lastSplineTime = 0 |
80 | spec.splineDiff = 0 |
81 | spec.electricitySpline = nil |
82 | |
83 | spec.lastVirtualRpm = self:getMotor():getMinRpm() |
84 | spec.speed = 0 |
85 | spec.lastAcceleration = 0 |
86 | spec.nextMovingDirection = 0 |
87 | |
88 | self:setLocomotiveState(Locomotive.STATE_NONE) |
89 | |
90 | spec.doStartCheck = true |
91 | end |
onUpdate
DescriptionDefinitiononUpdate()Code
95 | function Locomotive:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
96 | local spec = self.spec_locomotive |
97 | |
98 | if spec.doStartCheck then |
99 | if self:getIsReadyForAutomatedTrainTravel() then |
100 | spec.automaticTravelStartTime = g_time |
101 | self:setLocomotiveState(Locomotive.STATE_WAIT_FOR_AUTOMATIC_TRAVEL) |
102 | self:raiseActive() |
103 | |
104 | if self.setRandomVehicleCharacter ~= nil then |
105 | self:setRandomVehicleCharacter() |
106 | end |
107 | else |
108 | self:setLocomotiveState(Locomotive.STATE_MANUAL_TRAVEL_ACTIVE) |
109 | end |
110 | spec.doStartCheck = false |
111 | end |
112 | |
113 | -- update motor as long as locomotive is still moving but no player has entered |
114 | if self.isServer then |
115 | if spec.state == Locomotive.STATE_AUTOMATIC_TRAVEL_ACTIVE then |
116 | self:raiseActive() |
117 | self:updateVehiclePhysics(1, 0, 0, dt) |
118 | SpecializationUtil.raiseEvent(self, "onAutomatedTrainTravelActive", dt) |
119 | elseif spec.state == Locomotive.STATE_REQUESTED_POSITION then |
120 | if spec.requestedSplinePosition ~= nil then |
121 | local currentPosition = self:getCurrentSplinePosition() |
122 | local requestedPosition = spec.requestedSplinePosition |
123 | if currentPosition > spec.requestedSplinePosition then |
124 | requestedPosition = requestedPosition + 1 |
125 | end |
126 | |
127 | local brakeAcceleration = Locomotive.getBrakeAcceleration(self) |
128 | local brakeDistance = math.abs((spec.speed^2)/(2*brakeAcceleration)) |
129 | local brakePoint = requestedPosition - brakeDistance / self.trainSystem.splineLength |
130 | |
131 | if currentPosition > brakePoint then |
132 | self:setLocomotiveState(Locomotive.STATE_REQUESTED_POSITION_BRAKING) |
133 | else |
134 | self:updateVehiclePhysics(1, 0, 0, dt) |
135 | end |
136 | self:raiseActive() |
137 | end |
138 | elseif spec.state == Locomotive.STATE_REQUESTED_POSITION_BRAKING then |
139 | self:updateVehiclePhysics(-1, 0, 0, dt) |
140 | self:raiseActive() |
141 | if spec.speed == 0 then |
142 | self:setLocomotiveState(Locomotive.STATE_MANUAL_TRAVEL_ACTIVE) |
143 | end |
144 | elseif spec.state == Locomotive.STATE_WAIT_FOR_AUTOMATIC_TRAVEL then |
145 | self:raiseActive() |
146 | elseif spec.state == Locomotive.STATE_MANUAL_TRAVEL_INACTIVE then |
147 | if self.movingDirection > 0 then |
148 | self:updateVehiclePhysics(-1, 0, 0, dt) |
149 | else |
150 | self:updateVehiclePhysics(1, 0, 0, dt) |
151 | end |
152 | self:raiseActive() |
153 | if spec.speed == 0 then |
154 | if self:getIsReadyForAutomatedTrainTravel() then |
155 | self:setLocomotiveState(Locomotive.STATE_WAIT_FOR_AUTOMATIC_TRAVEL) |
156 | spec.automaticTravelStartTime = g_time + Locomotive.AUTOMATIC_DRIVE_DELAY |
157 | end |
158 | end |
159 | end |
160 | end |
161 | end |
onUpdateTick
DescriptionDefinitiononUpdateTick()Code
165 | function Locomotive:onUpdateTick(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
166 | if self.isServer then |
167 | local spec = self.spec_locomotive |
168 | if spec.state == Locomotive.STATE_WAIT_FOR_AUTOMATIC_TRAVEL then |
169 | if g_time > spec.automaticTravelStartTime then |
170 | self:setLocomotiveState(Locomotive.STATE_AUTOMATIC_TRAVEL_ACTIVE) |
171 | self:startMotor() |
172 | self:raiseActive() |
173 | end |
174 | end |
175 | end |
176 | end |
prerequisitesPresent
DescriptionChecks if all prerequisite specializations are loadedDefinition
prerequisitesPresent(table specializations)Arguments
table | specializations | specializations |
boolean | hasPrerequisite | true if all prerequisite specializations are loaded |
29 | function Locomotive.prerequisitesPresent(specializations) |
30 | return SpecializationUtil.hasSpecialization(SplineVehicle, specializations) and SpecializationUtil.hasSpecialization(Drivable, specializations) |
31 | end |
registerEventListeners
DescriptionDefinitionregisterEventListeners()Code
62 | function Locomotive.registerEventListeners(vehicleType) |
63 | SpecializationUtil.registerEventListener(vehicleType, "onLoad", Locomotive) |
64 | SpecializationUtil.registerEventListener(vehicleType, "onUpdate", Locomotive) |
65 | SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", Locomotive) |
66 | SpecializationUtil.registerEventListener(vehicleType, "onLeaveVehicle", Locomotive) |
67 | SpecializationUtil.registerEventListener(vehicleType, "onEnterVehicle", Locomotive) |
68 | end |
registerEvents
DescriptionDefinitionregisterEvents()Code
35 | function Locomotive.registerEvents(vehicleType) |
36 | SpecializationUtil.registerEvent(vehicleType, "onAutomatedTrainTravelActive") |
37 | end |
registerFunctions
DescriptionDefinitionregisterFunctions()Code
41 | function Locomotive.registerFunctions(vehicleType) |
42 | SpecializationUtil.registerFunction(vehicleType, "getDownhillForce", Locomotive.getDownhillForce) |
43 | SpecializationUtil.registerFunction(vehicleType, "setRequestedSplinePosition", Locomotive.setRequestedSplinePosition) |
44 | SpecializationUtil.registerFunction(vehicleType, "setLocomotiveState", Locomotive.setLocomotiveState) |
45 | end |
registerOverwrittenFunctions
DescriptionDefinitionregisterOverwrittenFunctions()Code
49 | function Locomotive.registerOverwrittenFunctions(vehicleType) |
50 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsMotorStarted", Locomotive.getIsMotorStarted) |
51 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "updateVehiclePhysics", Locomotive.updateVehiclePhysics) |
52 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsReadyForAutomatedTrainTravel", Locomotive.getIsReadyForAutomatedTrainTravel) |
53 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "alignToSplineTime", Locomotive.alignToSplineTime) |
54 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "setTrainSystem", Locomotive.setTrainSystem) |
55 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getFullName", Locomotive.getFullName) |
56 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getAreSurfaceSoundsActive", Locomotive.getAreSurfaceSoundsActive) |
57 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getTravedDistanceStatsActive", Locomotive.getTravedDistanceStatsActive) |
58 | end |
setLocomotiveState
DescriptionDefinitionsetLocomotiveState()Code
231 | function Locomotive:setLocomotiveState(state) |
232 | self.state = state |
233 | end |
setRequestedSplinePosition
DescriptionDefinitionsetRequestedSplinePosition()Code
217 | function Locomotive:setRequestedSplinePosition(splinePosition, noEventSend) |
218 | if not self.isServer then |
219 | -- client to server event only |
220 | g_client:getServerConnection():sendEvent(SendLocomotiveToSplinePositionEvent:new(self, splinePosition)) |
221 | end |
222 | |
223 | local spec = self.spec_locomotive |
224 | spec.requestedSplinePosition = splinePosition |
225 | self:setLocomotiveState(Locomotive.STATE_REQUESTED_POSITION) |
226 | self:startMotor() |
227 | end |
setTrainSystem
DescriptionDefinitionsetTrainSystem()Code
180 | function Locomotive:setTrainSystem(superFunc, trainSystem) |
181 | superFunc(self, trainSystem) |
182 | |
183 | local spec = self.spec_locomotive |
184 | if spec.powerArm ~= nil then |
185 | local spline = trainSystem:getElectricitySpline() |
186 | if spline ~= nil then |
187 | local electricitySplineLength = trainSystem:getElectricitySplineLength() |
188 | local splineLength = trainSystem:getSplineLength() |
189 | spec.splineDiff = math.abs(electricitySplineLength - splineLength) |
190 | spec.electricitySplineSearchTime = spec.splineDiff * 4 / electricitySplineLength |
191 | spec.electricitySpline = spline |
192 | end |
193 | end |
194 | end |
updateVehiclePhysics
DescriptionDefinitionupdateVehiclePhysics()Code
317 | function Locomotive:updateVehiclePhysics(superFunc, axisForward, axisSide, doHandbrake, dt) |
318 | local spec = self.spec_locomotive |
319 | local specDrivable = self.spec_drivable |
320 | local acceleration = superFunc(self, axisForward, axisSide, doHandbrake, dt) |
321 | |
322 | local interpDt = g_physicsDt |
323 | if g_server == nil then |
324 | -- on clients, we interpolate the vehicles with g_physicsDtUnclamped, thus we need to use the same for camera interpolation |
325 | interpDt = g_physicsDtUnclamped |
326 | end |
327 | |
328 | -- assuming: |
329 | -- totalMass: mass, |
330 | -- P(v): tractive effort of locomotive |
331 | -- Q(v): drag of train (dismissed) |
332 | -- B: brake force |
333 | -- g: gravity |
334 | -- alpha: inclination angle |
335 | -- |
336 | -- totalMass*a = P(v) - Q(v) - B - totalMass*g*sin(alpha) |
337 | -- a = 1/totalMass * [ (P(v) - Q(v) - B - totalMass*g*sin(alpha) ] |
338 | |
339 | local totalMass = self:getTotalMass(false) |
340 | local tractiveEffort = 300000 |
341 | local maxBrakeForce = totalMass * 9.81 * 0.18 |
342 | local brakeForce = maxBrakeForce |
343 | local downhillForce = spec:getDownhillForce() |
344 | tractiveEffort = math.min(tractiveEffort, maxBrakeForce) |
345 | |
346 | if self:getIsMotorStarted() and self:getMotorStartTime() <= g_currentMission.time then |
347 | local reverserDirection = specDrivable == nil and 1 or specDrivable.reverserDirection |
348 | if self:getCruiseControlState() ~= Drivable.CRUISECONTROL_STATE_OFF then |
349 | if spec.speed < reverserDirection * self:getCruiseControlSpeed() / 3.6 then |
350 | acceleration = 1 |
351 | elseif spec.speed > reverserDirection * self:getCruiseControlSpeed() / 3.6 then |
352 | acceleration = -1 |
353 | end |
354 | end |
355 | else |
356 | tractiveEffort = maxBrakeForce |
357 | end |
358 | |
359 | if math.abs(acceleration) < 0.001 then |
360 | local a = Locomotive.getBrakeAcceleration(self) |
361 | |
362 | if spec.speed > 0 then |
363 | spec.speed = math.max(0, spec.speed + a * dt/1000) |
364 | elseif spec.speed < 0 then |
365 | spec.speed = math.min(0, spec.speed + a * dt/1000) |
366 | else |
367 | -- move train if track is too steep ??? |
368 | if maxBrakeForce < math.abs(downhillForce) then |
369 | spec.speed = spec.speed + a * dt/1000 |
370 | end |
371 | end |
372 | |
373 | if spec.speed == 0 then |
374 | spec.hasStopped = true |
375 | else |
376 | spec.hasStopped = false |
377 | end |
378 | else |
379 | if math.abs(spec.speed) > 0.1 then |
380 | spec.hasStopped = false |
381 | elseif math.abs(spec.speed) == 0 then |
382 | spec.hasStopped = true |
383 | end |
384 | if spec.hasStopped == nil or (spec.hasStopped and math.abs(acceleration) > 0.01) then |
385 | spec.nextMovingDirection = MathUtil.sign(acceleration) |
386 | end |
387 | |
388 | local a = 0 |
389 | |
390 | if spec.nextMovingDirection == nil or (spec.nextMovingDirection * acceleration) > 0 then |
391 | tractiveEffort = acceleration * tractiveEffort |
392 | brakeForce = 0 |
393 | a = (1/totalMass) * ( tractiveEffort - brakeForce - downhillForce ) |
394 | else |
395 | tractiveEffort = 0 |
396 | brakeForce = MathUtil.sign(spec.speed) * math.abs(acceleration) * maxBrakeForce |
397 | if math.abs(spec.speed) < 0.1 then |
398 | spec.speed = 0 |
399 | else |
400 | a = (1/totalMass) * ( tractiveEffort - brakeForce - downhillForce ) |
401 | end |
402 | end |
403 | |
404 | spec.speed = spec.speed + a * interpDt/1000 |
405 | end |
406 | |
407 | if spec.speed > 0 then |
408 | spec.speed = math.min(spec.speed, self:getMotor():getMaximumForwardSpeed()) |
409 | elseif spec.speed < 0 then |
410 | spec.speed = math.max(spec.speed, -self:getMotor():getMaximumBackwardSpeed()) |
411 | end |
412 | |
413 | if spec.speed ~= 0 then |
414 | self.trainSystem:updateTrainPositionByLocomotiveSpeed(interpDt, spec.speed) |
415 | end |
416 | |
417 | local motor = self:getMotor() |
418 | local minRpm = motor:getMinRpm() |
419 | local maxRpm = motor:getMaxRpm() |
420 | -- fake rpm for indoorHud |
421 | if spec.lastAcceleration * spec.nextMovingDirection > 0 then |
422 | spec.lastVirtualRpm = math.min(maxRpm, spec.lastVirtualRpm + (0.0005 * dt * (maxRpm - minRpm))) |
423 | else |
424 | spec.lastVirtualRpm = math.max(minRpm, spec.lastVirtualRpm - (0.001 * dt * (maxRpm - minRpm))) |
425 | end |
426 | |
427 | motor:setEqualizedMotorRpm(spec.lastVirtualRpm) |
428 | |
429 | spec.lastAcceleration = acceleration |
430 | end |