LUADOC - Farming Simulator 19

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
434function 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
464end

getAreSurfaceSoundsActive

Description
Definition
getAreSurfaceSoundsActive()
Code
205function Locomotive:getAreSurfaceSoundsActive(superFunc)
206 return self:getLastSpeed() > 0.1
207end

getBrakeAcceleration

Description
Definition
getBrakeAcceleration()
Code
297function 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)
313end

getDownhillForce

Description
Definition
getDownhillForce()
Code
287function 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)
293end

getFullName

Description
Definition
getFullName()
Code
198function Locomotive:getFullName(superFunc)
199 local storeItem = g_storeManager:getItemByXMLFilename(self.configFileName)
200 return storeItem.name
201end

getIsMotorStarted

Description
Definition
getIsMotorStarted()
Code
277function 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
283end

getIsReadyForAutomatedTrainTravel

Description
Definition
getIsReadyForAutomatedTrainTravel()
Code
267function Locomotive:getIsReadyForAutomatedTrainTravel(superFunc)
268 if self:getIsControlled() then
269 return false
270 end
271
272 return superFunc(self)
273end

getTravedDistanceStatsActive

Description
Definition
getTravedDistanceStatsActive()
Code
211function Locomotive:getTravedDistanceStatsActive(superFunc)
212 return self.state == Locomotive.STATE_MANUAL_TRAVEL_ACTIVE
213end

onEnterVehicle

Description
Definition
onEnterVehicle()
Code
251function 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)
263end

onLeaveVehicle

Description
Definition
onLeaveVehicle()
Code
237function 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
247end

onLoad

Description
Called on loading
Definition
onLoad(table savegame)
Arguments
tablesavegamesavegame
Code
74function 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
91end

onUpdate

Description
Definition
onUpdate()
Code
95function 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
161end

onUpdateTick

Description
Definition
onUpdateTick()
Code
165function 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
176end

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

registerEventListeners

Description
Definition
registerEventListeners()
Code
62function 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)
68end

registerEvents

Description
Definition
registerEvents()
Code
35function Locomotive.registerEvents(vehicleType)
36 SpecializationUtil.registerEvent(vehicleType, "onAutomatedTrainTravelActive")
37end

registerFunctions

Description
Definition
registerFunctions()
Code
41function Locomotive.registerFunctions(vehicleType)
42 SpecializationUtil.registerFunction(vehicleType, "getDownhillForce", Locomotive.getDownhillForce)
43 SpecializationUtil.registerFunction(vehicleType, "setRequestedSplinePosition", Locomotive.setRequestedSplinePosition)
44 SpecializationUtil.registerFunction(vehicleType, "setLocomotiveState", Locomotive.setLocomotiveState)
45end

registerOverwrittenFunctions

Description
Definition
registerOverwrittenFunctions()
Code
49function 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)
58end

setLocomotiveState

Description
Definition
setLocomotiveState()
Code
231function Locomotive:setLocomotiveState(state)
232 self.state = state
233end

setRequestedSplinePosition

Description
Definition
setRequestedSplinePosition()
Code
217function 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()
227end

setTrainSystem

Description
Definition
setTrainSystem()
Code
180function 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
194end

updateVehiclePhysics

Description
Definition
updateVehiclePhysics()
Code
317function 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
430end