LUADOC - Farming Simulator 22

Drivable

Description
Specialization for cruise control, steering wheel; required Enterable and Motorized specialization
Functions

actionEventAccelerate

Description
Definition
actionEventAccelerate()
Code
1201function Drivable.actionEventAccelerate(self, actionName, inputValue, callbackState, isAnalog)
1202 if inputValue ~= 0 then
1203 self:setAccelerationPedalInput(inputValue)
1204 end
1205end

actionEventBrake

Description
Definition
actionEventBrake()
Code
1209function Drivable.actionEventBrake(self, actionName, inputValue, callbackState, isAnalog)
1210 if inputValue ~= 0 then
1211 self:setBrakePedalInput(inputValue)
1212 end
1213end

actionEventCruiseControlState

Description
Definition
actionEventCruiseControlState()
Code
1248function Drivable.actionEventCruiseControlState(self, actionName, inputValue, callbackState, isAnalog)
1249 local spec = self.spec_drivable
1250 spec.lastInputValues.cruiseControlState = 1
1251end

actionEventCruiseControlValue

Description
Definition
actionEventCruiseControlValue()
Code
1255function Drivable.actionEventCruiseControlValue(self, actionName, inputValue, callbackState, isAnalog)
1256 local spec = self.spec_drivable
1257 spec.lastInputValues.cruiseControlValue = inputValue
1258end

actionEventSteer

Description
Definition
actionEventSteer()
Code
1217function Drivable.actionEventSteer(self, actionName, inputValue, callbackState, isAnalog, isMouse, deviceCategory, binding)
1218 local spec = self.spec_drivable
1219 if not spec.forceFeedback.isActive then
1220 local isSupported, device, axisIndex = g_inputBinding:getBindingForceFeedbackInfo(binding)
1221 spec.forceFeedback.isActive = isSupported
1222 spec.forceFeedback.device = device
1223 spec.forceFeedback.binding = binding
1224 spec.forceFeedback.axisIndex = axisIndex
1225
1226 if isSupported then
1227 device:setForceFeedback(axisIndex, 0, inputValue)
1228 end
1229 else
1230 if binding ~= spec.forceFeedback.binding then
1231 local isSupported, _, _ = g_inputBinding:getBindingForceFeedbackInfo(binding)
1232 if not isSupported then
1233 spec.forceFeedback.isActive = false
1234 spec.forceFeedback.device = nil
1235 spec.forceFeedback.binding = nil
1236 spec.forceFeedback.axisIndex = 0
1237 end
1238 end
1239 end
1240
1241 if inputValue ~= 0 then
1242 self:setSteeringInput(inputValue, isAnalog, deviceCategory)
1243 end
1244end

brakeToStop

Description
Definition
brakeToStop()
Code
1162function Drivable:brakeToStop()
1163 local spec = self.spec_drivable
1164 spec.brakeToStop = true
1165end

getAccelerationAxis

Description
Definition
getAccelerationAxis()
Code
878function Drivable:getAccelerationAxis()
879 local dir = self.movingDirection > -1 and 1 or -1
880 return math.max(self.spec_drivable.axisForward * dir * self:getReverserDirection(), 0)
881end

getAcDecelerationAxis

Description
Definition
getAcDecelerationAxis()
Code
905function Drivable:getAcDecelerationAxis()
906 return self.spec_drivable.axisForward*self:getReverserDirection()
907end

getAxisForward

Description
Definition
getAxisForward()
Code
872function Drivable:getAxisForward()
873 return self.spec_drivable.axisForward
874end

getCruiseControlAxis

Description
Definition
getCruiseControlAxis()
Code
898function Drivable:getCruiseControlAxis()
899 return self.spec_drivable.cruiseControl.state ~= Drivable.CRUISECONTROL_STATE_OFF and 1 or 0
900end

getCruiseControlDisplayInfo

Description
Returns info to display in speed meter HUD
Definition
getCruiseControlDisplayInfo()
Return Values
floatcruiseControlSpeedcurrent cruise control speed
boolisActiveis cruise control active
Code
842function Drivable:getCruiseControlDisplayInfo()
843 local cruiseControlSpeed
844 local isActive = true
845
846 local cruiseControl = self.spec_drivable.cruiseControl
847 if self:getReverserDirection() < 0 then
848 cruiseControlSpeed = cruiseControl.speedReverse
849 else
850 cruiseControlSpeed = cruiseControl.speed
851 end
852
853 if cruiseControl.state == Drivable.CRUISECONTROL_STATE_FULL then
854 cruiseControlSpeed = cruiseControl.maxSpeed
855 elseif cruiseControl.state == Drivable.CRUISECONTROL_STATE_OFF then
856 isActive = false
857 end
858
859 if self:getDrivingDirection() < 0 then
860 if self:getReverserDirection() < 0 then
861 cruiseControlSpeed = cruiseControl.speed
862 else
863 cruiseControlSpeed = cruiseControl.speedReverse
864 end
865 end
866
867 return cruiseControlSpeed, isActive
868end

getCruiseControlMaxSpeed

Description
Definition
getCruiseControlMaxSpeed()
Code
834function Drivable:getCruiseControlMaxSpeed()
835 return self.spec_drivable.cruiseControl.maxSpeed
836end

getCruiseControlSpeed

Description
Definition
getCruiseControlSpeed()
Code
823function Drivable:getCruiseControlSpeed()
824 local spec = self.spec_drivable
825 if spec.cruiseControl.state == Drivable.CRUISECONTROL_STATE_FULL then
826 return spec.cruiseControl.maxSpeed
827 end
828
829 return spec.cruiseControl.speed
830end

getCruiseControlState

Description
Definition
getCruiseControlState()
Code
817function Drivable:getCruiseControlState()
818 return self.spec_drivable.cruiseControl.state
819end

getDashboardSteeringAxis

Description
Definition
getDashboardSteeringAxis()
Code
911function Drivable:getDashboardSteeringAxis()
912 local spec = self.spec_drivable
913 if spec.idleTurningAllowed then
914 if spec.idleTurningActive and not spec.idleTurningUpdateSteeringWheel then
915 return 0
916 end
917 end
918
919 return self.rotatedTime * self:getReverserDirection()
920end

getDecelerationAxis

Description
Definition
getDecelerationAxis()
Code
886function Drivable:getDecelerationAxis()
887 -- if moving backward and accelrating forward the threshold for the brake pedal is at 7.2km/h to avoid quick brake and gas pedal switches
888 if self.lastSpeedReal > 0.0001 and (self.movingDirection == MathUtil.sign(self.spec_drivable.axisForward) or self.lastSpeedReal > 0.002) then
889 return math.abs(math.min(self.spec_drivable.axisForward*self.movingDirection*self:getReverserDirection(), 0))
890 end
891
892 return 0
893end

getDrivingDirection

Description
Definition
getDrivingDirection()
Code
954function Drivable:getDrivingDirection()
955 local lastSpeed = self:getLastSpeed()
956 if lastSpeed < 0.2 then
957 return 0
958 end
959
960 if lastSpeed < 1.5 then
961 -- if we are not pressing any button the speed change could be caused by outer influences
962 if self.spec_drivable.axisForward == 0 then
963 return 0
964 end
965 end
966
967 return self.movingDirection * self:getReverserDirection()
968end

getIsDrivingBackward

Description
Definition
getIsDrivingBackward()
Code
948function Drivable:getIsDrivingBackward()
949 return self:getDrivingDirection() < 0
950end

getIsDrivingForward

Description
Definition
getIsDrivingForward()
Code
942function Drivable:getIsDrivingForward()
943 return self:getDrivingDirection() >= 0
944end

getIsManualDirectionChangeAllowed

Description
Definition
getIsManualDirectionChangeAllowed()
Code
1190function Drivable:getIsManualDirectionChangeAllowed(superFunc)
1191 local spec = self.spec_drivable
1192 if spec.idleTurningAllowed and spec.idleTurningActive then
1193 return false
1194 end
1195
1196 return superFunc(self)
1197end

getIsVehicleControlledByPlayer

Description
Definition
getIsVehicleControlledByPlayer()
Code
973function Drivable:getIsVehicleControlledByPlayer()
974 return true
975end

getReverserDirection

Description
Definition
getReverserDirection()
Code
930function Drivable:getReverserDirection()
931 return self.spec_drivable.reverserDirection
932end

getSteeringDirection

Description
Definition
getSteeringDirection()
Code
936function Drivable:getSteeringDirection()
937 return 1
938end

initSpecialization

Description
Definition
initSpecialization()
Code
32function Drivable.initSpecialization()
33 local schema = Vehicle.xmlSchema
34 schema:setXMLSpecializationType("Drivable")
35
36 schema:register(XMLValueType.FLOAT, "vehicle.drivable.speedRotScale#scale", "Speed dependent steering speed scale", 80)
37 schema:register(XMLValueType.FLOAT, "vehicle.drivable.speedRotScale#offset", "Speed dependent steering speed offset", 0.7)
38
39 schema:register(XMLValueType.FLOAT, "vehicle.drivable.cruiseControl#maxSpeed", "Max. cruise control speed", "Max. vehicle speed")
40 schema:register(XMLValueType.FLOAT, "vehicle.drivable.cruiseControl#minSpeed", "Min. cruise control speed", 1)
41 schema:register(XMLValueType.FLOAT, "vehicle.drivable.cruiseControl#maxSpeedReverse", "Max. cruise control speed in reverse", "Max. value reverse speed")
42 schema:register(XMLValueType.BOOL, "vehicle.drivable.cruiseControl#enabled", "Cruise control enabled", true)
43
44 schema:register(XMLValueType.NODE_INDEX, "vehicle.drivable.steeringWheel#node", "Steering wheel node")
45 schema:register(XMLValueType.ANGLE, "vehicle.drivable.steeringWheel#indoorRotation", "Steering wheel indoor rotation", 0)
46 schema:register(XMLValueType.ANGLE, "vehicle.drivable.steeringWheel#outdoorRotation", "Steering wheel outdoor rotation", 0)
47
48 schema:register(XMLValueType.BOOL, "vehicle.drivable.idleTurning#allowed", "When vehicle is not moving and steering keys are pressed turns on the same spot", false)
49 schema:register(XMLValueType.BOOL, "vehicle.drivable.idleTurning#updateSteeringWheel", "Update steering wheel", true)
50 schema:register(XMLValueType.BOOL, "vehicle.drivable.idleTurning#lockDirection", "Defines if the direction is locked until player accelerates again", true)
51 schema:register(XMLValueType.INT, "vehicle.drivable.idleTurning#direction", "Driving direction [-1, 1]", 1)
52 schema:register(XMLValueType.FLOAT, "vehicle.drivable.idleTurning#maxSpeed", "Max. speed while turning", 10)
53 schema:register(XMLValueType.FLOAT, "vehicle.drivable.idleTurning#steeringFactor", "Steering speed factor", 100)
54 schema:register(XMLValueType.NODE_INDEX, "vehicle.drivable.idleTurning.wheel(?)#node", "Wheel node to change")
55 schema:register(XMLValueType.ANGLE, "vehicle.drivable.idleTurning.wheel(?)#steeringAngle", "Steering angle while idle turning")
56 schema:register(XMLValueType.BOOL, "vehicle.drivable.idleTurning.wheel(?)#inverted", "Acceleration is inverted", false)
57
58 Dashboard.registerDashboardXMLPaths(schema, "vehicle.drivable.dashboards", "cruiseControl | directionForward | directionBackward | movingDirection | cruiseControlActive | accelerationAxis | decelerationAxis | ac_decelerationAxis | steeringAngle")
59 SoundManager.registerSampleXMLPaths(schema, "vehicle.drivable.sounds", "waterSplash")
60
61 schema:setXMLSpecializationType()
62
63 local schemaSavegame = Vehicle.xmlSchemaSavegame
64 schemaSavegame:register(XMLValueType.INT, "vehicles.vehicle(?).drivable#cruiseControl", "Current cruise control speed")
65 schemaSavegame:register(XMLValueType.INT, "vehicles.vehicle(?).drivable#cruiseControlReverse", "Current cruise control speed reverse")
66end

onDelete

Description
Called on deleting
Definition
onDelete()
Code
295function Drivable:onDelete()
296 local spec = self.spec_drivable
297 g_soundManager:deleteSamples(spec.samples)
298end

onLeaveVehicle

Description
Definition
onLeaveVehicle()
Code
1027function Drivable:onLeaveVehicle(wasEntered)
1028 self:setCruiseControlState(Drivable.CRUISECONTROL_STATE_OFF)
1029
1030 if self.brake ~= nil then
1031 self:brake(1)
1032 end
1033
1034 if wasEntered then
1035 local spec = self.spec_drivable
1036 local forceFeedback = spec.forceFeedback
1037 if forceFeedback.isActive then
1038 forceFeedback.device:setForceFeedback(forceFeedback.axisIndex, 0, 0)
1039 forceFeedback.isActive = false
1040 forceFeedback.device = nil
1041 end
1042 end
1043end

onLoad

Description
Called on loading
Definition
onLoad(table savegame)
Arguments
tablesavegamesavegame
Code
130function Drivable:onLoad(savegame)
131 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.steering#index", "vehicle.drivable.steeringWheel#node") --FS17 to FS19
132 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.steering#node", "vehicle.drivable.steeringWheel#node") --FS17 to FS19
133 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.cruiseControl", "vehicle.drivable.cruiseControl") --FS17 to FS19
134 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.indoorHud.cruiseControl", "vehicle.drivable.dashboards.dashboard with valueType 'cruiseControl'") --FS17 to FS19
135 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.showChangeToolSelectionHelp") --FS17 to FS19
136 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.maxRotatedTimeSpeed#value") --FS17 to FS19
137 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.speedRotScale#scale", "vehicle.drivable.speedRotScale#scale") --FS17 to FS19
138 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.speedRotScale#offset", "vehicle.drivable.speedRotScale#offset") --FS17 to FS19
139
140 local spec = self.spec_drivable
141
142 spec.showToolSelectionHud = true
143
144 spec.doHandbrake = false
145 spec.doHandbrakeSend = false
146 spec.reverserDirection = 1
147
148 -- attributes set by action events
149 spec.lastInputValues = {}
150 spec.lastInputValues.axisAccelerate = 0
151 spec.lastInputValues.axisBrake = 0
152 spec.lastInputValues.axisSteer = 0
153 spec.lastInputValues.axisSteerIsAnalog = false
154 spec.lastInputValues.axisSteerDeviceCategory = InputDevice.CATEGORY.UNKNOWN
155 spec.lastInputValues.cruiseControlValue = 0
156 spec.lastInputValues.cruiseControlState = 0
157
158 -- 'final' attrbutes calculated
159 spec.axisForward = 0
160 spec.axisForwardSend = 0
161
162 spec.axisSide = 0
163 spec.axisSideSend = 0
164 spec.axisSideLast = 0
165
166 spec.lastIsControlled = false
167
168 spec.speedRotScale = self.xmlFile:getValue("vehicle.drivable.speedRotScale#scale", 80)
169 spec.speedRotScaleOffset = self.xmlFile:getValue("vehicle.drivable.speedRotScale#offset", 0.7)
170
171 local motor = self:getMotor()
172 spec.cruiseControl = {}
173 spec.cruiseControl.maxSpeed = self.xmlFile:getValue("vehicle.drivable.cruiseControl#maxSpeed", MathUtil.round(motor:getMaximumForwardSpeed()*3.6))
174 spec.cruiseControl.minSpeed = self.xmlFile:getValue("vehicle.drivable.cruiseControl#minSpeed", math.min(1, spec.cruiseControl.maxSpeed))
175 spec.cruiseControl.speed = spec.cruiseControl.maxSpeed
176 spec.cruiseControl.maxSpeedReverse = self.xmlFile:getValue("vehicle.drivable.cruiseControl#maxSpeedReverse", MathUtil.round(motor:getMaximumBackwardSpeed()*3.6))
177 spec.cruiseControl.speedReverse = spec.cruiseControl.maxSpeedReverse
178 spec.cruiseControl.isActive = self.xmlFile:getValue("vehicle.drivable.cruiseControl#enabled", true)
179 spec.cruiseControl.state = Drivable.CRUISECONTROL_STATE_OFF
180 spec.cruiseControl.topSpeedTime = 1000
181 spec.cruiseControl.changeDelay = 250
182 spec.cruiseControl.changeCurrentDelay = 0
183 spec.cruiseControl.changeMultiplier = 1
184 spec.cruiseControl.speedSent = spec.cruiseControl.speed
185 spec.cruiseControl.speedReverseSent = spec.cruiseControl.speedReverse
186
187 local node = self.xmlFile:getValue("vehicle.drivable.steeringWheel#node", nil, self.components, self.i3dMappings)
188 if node ~= nil then
189 spec.steeringWheel = {}
190 spec.steeringWheel.node = node
191 local _,ry,_ = getRotation(spec.steeringWheel.node)
192 spec.steeringWheel.lastRotation = ry
193 spec.steeringWheel.indoorRotation = self.xmlFile:getValue("vehicle.drivable.steeringWheel#indoorRotation", 0)
194 spec.steeringWheel.outdoorRotation = self.xmlFile:getValue("vehicle.drivable.steeringWheel#outdoorRotation", 0)
195 end
196
197 spec.idleTurningAllowed = self.xmlFile:getValue("vehicle.drivable.idleTurning#allowed", false)
198 spec.idleTurningUpdateSteeringWheel = self.xmlFile:getValue("vehicle.drivable.idleTurning#updateSteeringWheel", true)
199 spec.idleTurningLockDirection = self.xmlFile:getValue("vehicle.drivable.idleTurning#lockDirection", true)
200 spec.idleTurningDrivingDirection = self.xmlFile:getValue("vehicle.drivable.idleTurning#direction", 1)
201 spec.idleTurningMaxSpeed = self.xmlFile:getValue("vehicle.drivable.idleTurning#maxSpeed", 10)
202 spec.idleTurningSteeringFactor = self.xmlFile:getValue("vehicle.drivable.idleTurning#steeringFactor", 100)
203
204 spec.idleTurningWheels = {}
205 self.xmlFile:iterate("vehicle.drivable.idleTurning.wheel", function(index, key)
206 local wheelNode = self.xmlFile:getValue(key .. "#node", nil, self.components, self.i3dMappings)
207 if wheelNode ~= nil then
208 local entry = {}
209 entry.wheelNode = wheelNode
210 entry.steeringAngle = self.xmlFile:getValue(key .. "#steeringAngle", 0)
211 entry.inverted = self.xmlFile:getValue(key .. "#inverted", false)
212
213 table.insert(spec.idleTurningWheels, entry)
214 end
215 end)
216
217
218 spec.idleTurningActive = false
219 spec.idleTurningDirection = 0
220
221 self.customSteeringAngleFunction = self.customSteeringAngleFunction or #spec.idleTurningWheels > 0
222
223 spec.forceFeedback = {}
224 spec.forceFeedback.isActive = false
225 spec.forceFeedback.device = nil
226 spec.forceFeedback.binding = nil
227 spec.forceFeedback.axisIndex = 0
228 spec.forceFeedback.intensity = g_gameSettings:getValue(GameSettings.SETTING.FORCE_FEEDBACK)
229
230 if self.loadDashboardsFromXML ~= nil then
231 local dashKey = "vehicle.drivable.dashboards"
232 self:loadDashboardsFromXML(self.xmlFile, dashKey, {valueTypeToLoad = "cruiseControl",
233 valueObject = spec.cruiseControl,
234 valueFunc = "speed"})
235
236 self:loadDashboardsFromXML(self.xmlFile, dashKey, {valueTypeToLoad = "directionForward",
237 valueObject = self,
238 valueFunc = "getIsDrivingForward"})
239
240 self:loadDashboardsFromXML(self.xmlFile, dashKey, {valueTypeToLoad = "directionBackward",
241 valueObject = self,
242 valueFunc = "getIsDrivingBackward"})
243
244 self:loadDashboardsFromXML(self.xmlFile, dashKey, {valueTypeToLoad = "movingDirection",
245 valueObject = self,
246 valueFunc = "getDrivingDirection",
247 minFunc = -1,
248 maxFunc = 1})
249
250 self:loadDashboardsFromXML(self.xmlFile, dashKey, {valueTypeToLoad = "cruiseControlActive",
251 valueObject = spec.cruiseControl,
252 valueFunc = "state",
253 valueCompare = Drivable.CRUISECONTROL_STATE_ACTIVE})
254
255 self:loadDashboardsFromXML(self.xmlFile, dashKey, {valueTypeToLoad = "accelerationAxis",
256 valueObject = self,
257 valueFunc = "getAccelerationAxis"})
258
259 self:loadDashboardsFromXML(self.xmlFile, dashKey, {valueTypeToLoad = "decelerationAxis",
260 valueObject = self,
261 valueFunc = "getDecelerationAxis"})
262
263 self:loadDashboardsFromXML(self.xmlFile, dashKey, {valueTypeToLoad = "ac_decelerationAxis",
264 valueObject = self,
265 valueFunc = "getAcDecelerationAxis"})
266
267 self:loadDashboardsFromXML(self.xmlFile, dashKey, {valueTypeToLoad = "steeringAngle",
268 valueObject = self,
269 valueFunc = "getDashboardSteeringAxis",
270 minFunc = -1,
271 maxFunc = 1})
272 end
273
274 if self.isClient then
275 spec.samples = {}
276 spec.samples.waterSplash = g_soundManager:loadSampleFromXML(self.xmlFile, "vehicle.drivable.sounds", "waterSplash", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self)
277 if self.isClient and g_isDevelopmentVersion then
278 if spec.samples.waterSplash == nil then
279 Logging.xmlDevWarning(self.xmlFile, "Missing drivable waterSplash sound")
280 end
281 end
282 end
283
284 if savegame ~= nil then
285 local maxSpeed = savegame.xmlFile:getValue(savegame.key..".drivable#cruiseControl")
286 local maxSpeedReverse = savegame.xmlFile:getValue(savegame.key..".drivable#cruiseControlReverse")
287 self:setCruiseControlMaxSpeed(maxSpeed, maxSpeedReverse)
288 end
289
290 spec.dirtyFlag = self:getNextDirtyFlag()
291end

onReadStream

Description
Called on client side on join
Definition
onReadStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
312function Drivable:onReadStream(streamId, connection)
313 local spec = self.spec_drivable
314
315 if spec.cruiseControl.isActive then
316 self:setCruiseControlState(streamReadUIntN(streamId, 2), true)
317 local speed = streamReadUInt8(streamId)
318 local speedReverse = streamReadUInt8(streamId)
319 self:setCruiseControlMaxSpeed(speed, speedReverse)
320 spec.cruiseControl.speedSent = speed
321 spec.cruiseControl.speedReverseSent = speedReverse
322 end
323end

onReadUpdateStream

Description
Called on on update
Definition
onReadUpdateStream(integer streamId, integer timestamp, table connection)
Arguments
integerstreamIdstream ID
integertimestamptimestamp
tableconnectionconnection
Code
344function Drivable:onReadUpdateStream(streamId, timestamp, connection)
345 local spec = self.spec_drivable
346
347 if streamReadBool(streamId) then
348 spec.axisForward = streamReadUIntN(streamId, 10) / 1023 * 2 - 1
349 if math.abs(spec.axisForward) < 0.00099 then
350 spec.axisForward = 0 -- set to 0 to avoid noise caused by compression
351 end
352
353 spec.axisSide = streamReadUIntN(streamId, 10) / 1023 * 2 - 1
354 if math.abs(spec.axisSide) < 0.00099 then
355 spec.axisSide = 0 -- set to 0 to avoid noise caused by compression
356 end
357
358 spec.doHandbrake = streamReadBool(streamId)
359 end
360end

onRegisterActionEvents

Description
Definition
onRegisterActionEvents()
Code
986function Drivable:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection)
987 if self.isClient then
988 local spec = self.spec_drivable
989
990 spec.toggleCruiseControlEvent = nil
991 self:clearActionEventsTable(spec.actionEvents)
992
993 local entered = true
994 if self.getIsEntered ~= nil then
995 entered = self:getIsEntered()
996 end
997
998 local _, actionEventId
999
1000 if self:getIsActiveForInput(true, true) and entered then
1001 if not self:getIsAIActive() then
1002 _, actionEventId = self:addPoweredActionEvent(spec.actionEvents, InputAction.AXIS_ACCELERATE_VEHICLE, self, Drivable.actionEventAccelerate, false, false, true, true, nil)
1003 g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_VERY_LOW)
1004 g_inputBinding:setActionEventTextVisibility(actionEventId, false)
1005 _, actionEventId = self:addPoweredActionEvent(spec.actionEvents, InputAction.AXIS_BRAKE_VEHICLE, self, Drivable.actionEventBrake, false, false, true, true, nil)
1006 g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_VERY_LOW)
1007 g_inputBinding:setActionEventTextVisibility(actionEventId, false)
1008 _, actionEventId = self:addPoweredActionEvent(spec.actionEvents, InputAction.AXIS_MOVE_SIDE_VEHICLE, self, Drivable.actionEventSteer, false, false, true, true, nil)
1009 g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_VERY_LOW)
1010 g_inputBinding:setActionEventTextVisibility(actionEventId, false)
1011 g_inputBinding:setActionEventText(actionEventId, g_i18n:getText("action_steer"))
1012
1013 _, actionEventId = self:addActionEvent(spec.actionEvents, InputAction.TOGGLE_CRUISE_CONTROL, self, Drivable.actionEventCruiseControlState, false, true, true, true, nil)
1014 g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_LOW)
1015 spec.toggleCruiseControlEvent = actionEventId
1016 end
1017
1018 _, actionEventId = self:addActionEvent(spec.actionEvents, InputAction.AXIS_CRUISE_CONTROL, self, Drivable.actionEventCruiseControlValue, false, true, true, true, nil)
1019 g_inputBinding:setActionEventText(actionEventId, g_i18n:getText("action_changeCruiseControlLevel"))
1020 g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_LOW)
1021 end
1022 end
1023end

onSetBroken

Description
Definition
onSetBroken()
Code
1047function Drivable:onSetBroken()
1048 if self.isClient then
1049 local spec = self.spec_drivable
1050 g_soundManager:playSample(spec.samples.waterSplash)
1051 end
1052end

onUpdate

Description
Definition
onUpdate()
Code
383function Drivable:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
384 local spec = self.spec_drivable
385
386 -- update inputs on client side for basic controls
387 if self.isClient then
388 if self.getIsEntered ~= nil and self:getIsEntered() then
389 if self.isActiveForInputIgnoreSelectionIgnoreAI then
390 if self:getIsVehicleControlledByPlayer() then
391 local lastSpeed = self:getLastSpeed()
392 spec.doHandbrake = false
393
394 -- gas and brake pedal
395 local axisForward = MathUtil.clamp((spec.lastInputValues.axisAccelerate - spec.lastInputValues.axisBrake), -1, 1)
396 spec.axisForward = axisForward
397
398 -- brake until we reach 1 km/h if brakeToStop is active
399 if spec.brakeToStop then
400 spec.lastInputValues.targetSpeed = 0.51
401 spec.lastInputValues.targetDirection = 1
402
403 if lastSpeed < 1 then
404 spec.brakeToStop = false
405
406 spec.lastInputValues.targetSpeed = nil
407 spec.lastInputValues.targetDirection = nil
408 end
409 end
410
411 -- axis forward calculated by current target speed
412 if spec.lastInputValues.targetSpeed ~= nil then
413 local currentSpeed = lastSpeed * self.movingDirection
414 local targetSpeed = spec.lastInputValues.targetSpeed * spec.lastInputValues.targetDirection
415
416 local speedDifference = targetSpeed - currentSpeed
417 if math.abs(speedDifference) > 0.1 and math.abs(targetSpeed) > 0.5 then
418 spec.axisForward = MathUtil.clamp(speedDifference * 0.1, -1, 1)
419 end
420 end
421
422 -- steering
423 if self:getIsPowered() then
424 local speedFactor = 1.0
425 local sensitivitySetting = g_gameSettings:getValue(GameSettings.SETTING.STEERING_SENSITIVITY)
426
427 local axisSteer = spec.lastInputValues.axisSteer
428
429 if spec.lastInputValues.axisSteerIsAnalog then
430 local isArticulatedSteering = self.spec_articulatedAxis ~= nil and self.spec_articulatedAxis.componentJoint ~= nil
431 if isArticulatedSteering then
432 speedFactor = 1.5
433 else
434 speedFactor = 2.5
435 end
436
437 if GS_IS_MOBILE_VERSION then
438 -- Fixed speed factor on mobile, and instead control non-linearity with sensitivity slider
439 --speedFactor = speedFactor * math.min(1.0/(self.lastSpeed*spec.speedRotScale+spec.speedRotScaleOffset), 1)
440
441 speedFactor = speedFactor * 1.5
442 axisSteer = math.pow(math.abs(axisSteer), 1.0/sensitivitySetting) * (axisSteer >= 0 and 1 or -1)
443 else
444 -- only use steering speed for gamepads
445 if spec.lastInputValues.axisSteerDeviceCategory == InputDevice.CATEGORY.GAMEPAD then
446 speedFactor = speedFactor * sensitivitySetting
447 end
448 end
449
450 local forceFeedback = spec.forceFeedback
451 if forceFeedback.isActive then
452 if forceFeedback.intensity > 0 then
453 local angleFactor = math.abs(axisSteer)
454 local speedForceFactor = math.max(math.min((lastSpeed-2) / 15, 1), 0)
455 local targetState = axisSteer - (0.2 * speedForceFactor) * MathUtil.sign(axisSteer)
456 local force = math.max(math.abs(targetState) * 0.4, 0.25) * speedForceFactor * angleFactor * 2 * forceFeedback.intensity
457 forceFeedback.device:setForceFeedback(forceFeedback.axisIndex, force, targetState)
458 else
459 forceFeedback.device:setForceFeedback(forceFeedback.axisIndex, 0, axisSteer)
460 end
461 end
462 else
463 if spec.lastInputValues.axisSteer == 0 then
464 local rotateBackSpeedSetting = g_gameSettings:getValue(GameSettings.SETTING.STEERING_BACK_SPEED) / 10
465
466 -- if the setting is '1' we use the same speed as we use for steering
467 -- if the setting is smaller '1' we reduce the steering angle depending on the driving speed
468 if rotateBackSpeedSetting < 1 and self.speedDependentRotateBack then
469 local speed = lastSpeed / 36
470 local setting = rotateBackSpeedSetting / 0.5
471 speedFactor = speedFactor * math.min(speed * setting, 1)
472 end
473
474 speedFactor = speedFactor * (self.autoRotateBackSpeed or 1) / 1.5
475 else
476 speedFactor = math.min(1.0/(self.lastSpeed*spec.speedRotScale+spec.speedRotScaleOffset), 1)
477 speedFactor = speedFactor * sensitivitySetting
478 end
479 end
480
481 -- idle turning
482 if spec.idleTurningAllowed then
483 if axisForward == 0 and axisSteer ~= 0 and lastSpeed < 1 then
484 if not spec.idleTurningActive then
485 spec.idleTurningActive = true
486 spec.idleTurningDirection = MathUtil.sign(axisSteer) * spec.idleTurningDrivingDirection
487 end
488 end
489
490 if axisForward ~= 0 then
491 if spec.idleTurningActive then
492 spec.idleTurningActive = false
493 end
494 end
495
496 if spec.idleTurningActive then
497 if not spec.idleTurningLockDirection then
498 spec.idleTurningDirection = spec.idleTurningDrivingDirection
499
500 if axisSteer == 0 then
501 spec.idleTurningActive = false
502 spec.axisSide = 0
503 end
504 end
505 end
506
507 if spec.idleTurningActive then
508 spec.axisForward = spec.idleTurningDirection * MathUtil.sign(axisSteer)
509
510 axisSteer = math.abs(axisSteer) * spec.idleTurningDirection
511 speedFactor = speedFactor * spec.idleTurningSteeringFactor
512 end
513 end
514
515 local steeringDuration = (self.wheelSteeringDuration or 1) * 1000
516 local rotDelta = (dt / steeringDuration) * speedFactor
517
518 if axisSteer > spec.axisSide then
519 spec.axisSide = math.min(axisSteer, spec.axisSide + rotDelta)
520 elseif axisSteer < spec.axisSide then
521 spec.axisSide = math.max(axisSteer, spec.axisSide - rotDelta)
522 end
523 end
524 else
525 spec.axisForward = 0
526 spec.idleTurningModeActive = false
527 if self.rotatedTime < 0 then
528 spec.axisSide = self.rotatedTime / -self.maxRotTime / self:getSteeringDirection()
529 else
530 spec.axisSide = self.rotatedTime / self.minRotTime / self:getSteeringDirection()
531 end
532 end
533 else
534 spec.doHandbrake = true
535 spec.axisForward = 0
536 spec.idleTurningModeActive = false
537 end
538
539 -- prepare for next frame
540 spec.lastInputValues.axisAccelerate = 0
541 spec.lastInputValues.axisBrake = 0
542 spec.lastInputValues.axisSteer = 0
543
544 -- prepare network update
545 if spec.axisForward ~= spec.axisForwardSend or spec.axisSide ~= spec.axisSideSend or spec.doHandbrake ~= spec.doHandbrakeSend then
546 spec.axisForwardSend = spec.axisForward
547 spec.axisSideSend = spec.axisSide
548 spec.doHandbrakeSend = spec.doHandbrake
549 self:raiseDirtyFlags(spec.dirtyFlag)
550 end
551 end
552 end
553
554 -- update inputs on client side for cruise control
555 if self.isClient then
556 if self.getIsEntered ~= nil and self:getIsEntered() then
557 -- cruise control state
558 local inputValue = spec.lastInputValues.cruiseControlState
559 spec.lastInputValues.cruiseControlState = 0
560
561 if inputValue == 1 then
562 if spec.cruiseControl.topSpeedTime == Drivable.CRUISECONTROL_FULL_TOGGLE_TIME then
563 if spec.cruiseControl.state == Drivable.CRUISECONTROL_STATE_OFF then
564 self:setCruiseControlState(Drivable.CRUISECONTROL_STATE_ACTIVE)
565 else
566 self:setCruiseControlState(Drivable.CRUISECONTROL_STATE_OFF)
567 end
568 end
569
570 if spec.cruiseControl.topSpeedTime > 0 then
571 spec.cruiseControl.topSpeedTime = spec.cruiseControl.topSpeedTime - dt
572 if spec.cruiseControl.topSpeedTime < 0 then
573 self:setCruiseControlState(Drivable.CRUISECONTROL_STATE_FULL)
574 end
575 end
576 else
577 spec.cruiseControl.topSpeedTime = Drivable.CRUISECONTROL_FULL_TOGGLE_TIME
578 end
579
580 -- cruise control value
581 local lastCruiseControlValue = spec.lastInputValues.cruiseControlValue
582 spec.lastInputValues.cruiseControlValue = 0
583
584 if lastCruiseControlValue ~= 0 then
585 spec.cruiseControl.changeCurrentDelay = spec.cruiseControl.changeCurrentDelay - (dt * spec.cruiseControl.changeMultiplier)
586 spec.cruiseControl.changeMultiplier = math.min(spec.cruiseControl.changeMultiplier + (dt * 0.003), 10)
587
588 if spec.cruiseControl.changeCurrentDelay < 0 then
589 spec.cruiseControl.changeCurrentDelay = spec.cruiseControl.changeDelay
590
591 local dir = MathUtil.sign(lastCruiseControlValue)
592
593 local speed, speedReverse = spec.cruiseControl.speed, spec.cruiseControl.speedReverse
594 local useReverseSpeed = self:getDrivingDirection() < 0
595 if self:getReverserDirection() < 0 then
596 useReverseSpeed = not useReverseSpeed
597 end
598
599 if useReverseSpeed then
600 speedReverse = speedReverse + dir
601 else
602 speed = speed + dir
603 end
604
605 self:setCruiseControlMaxSpeed(speed, speedReverse)
606
607 if spec.cruiseControl.speed ~= spec.cruiseControl.speedSent or spec.cruiseControl.speedReverse ~= spec.cruiseControl.speedReverseSent then
608 if g_server ~= nil then
609 g_server:broadcastEvent(SetCruiseControlSpeedEvent.new(self, spec.cruiseControl.speed, spec.cruiseControl.speedReverse), nil, nil, self)
610 else
611 g_client:getServerConnection():sendEvent(SetCruiseControlSpeedEvent.new(self, spec.cruiseControl.speed, spec.cruiseControl.speedReverse))
612 end
613 spec.cruiseControl.speedSent = spec.cruiseControl.speed
614 spec.cruiseControl.speedReverseSent = spec.cruiseControl.speedReverse
615 end
616 end
617 else
618 spec.cruiseControl.changeCurrentDelay = 0
619 spec.cruiseControl.changeMultiplier = 1
620 end
621
622 end
623 end
624
625 local isControlled = self.getIsControlled ~= nil and self:getIsControlled()
626
627 -- update vehicle physics on server side
628 if self:getIsVehicleControlledByPlayer() then
629 if self.isServer then
630 if isControlled then
631 local cruiseControlSpeed = math.huge
632 if spec.cruiseControl.state == Drivable.CRUISECONTROL_STATE_ACTIVE then
633 if self:getReverserDirection() < 0 then
634 cruiseControlSpeed = spec.cruiseControl.speedReverse
635 else
636 cruiseControlSpeed = spec.cruiseControl.speed
637 end
638 end
639 if self:getDrivingDirection() < 0 then
640 if self:getReverserDirection() < 0 then
641 cruiseControlSpeed = math.min(cruiseControlSpeed, spec.cruiseControl.speed)
642 else
643 cruiseControlSpeed = math.min(cruiseControlSpeed, spec.cruiseControl.speedReverse)
644 end
645 end
646
647 -- while cruise control is active we interpolate between the speed while changing them
648 -- this reduces the peak motor load while this change happens
649 if cruiseControlSpeed ~= math.huge then
650 spec.cruiseControl.speedInterpolated = spec.cruiseControl.speedInterpolated or cruiseControlSpeed
651 if cruiseControlSpeed ~= spec.cruiseControl.speedInterpolated then
652 local diff = cruiseControlSpeed - spec.cruiseControl.speedInterpolated
653 local dir = MathUtil.sign(diff)
654 local limit = dir == 1 and math.min or math.max
655 spec.cruiseControl.speedInterpolated = limit(spec.cruiseControl.speedInterpolated + dt * 0.0025 * math.max(1, math.abs(diff)) * dir, cruiseControlSpeed)
656 cruiseControlSpeed = spec.cruiseControl.speedInterpolated
657 end
658 else
659 spec.cruiseControl.speedInterpolated = nil
660 end
661
662 local maxSpeed, _ = self:getSpeedLimit(true)
663 maxSpeed = math.min(maxSpeed, cruiseControlSpeed)
664
665 if spec.idleTurningAllowed then
666 if spec.idleTurningActive then
667 maxSpeed = math.min(maxSpeed, spec.idleTurningMaxSpeed)
668 end
669 end
670
671 self:getMotor():setSpeedLimit(maxSpeed)
672
673 self:updateVehiclePhysics(spec.axisForward, spec.axisSide, spec.doHandbrake, dt)
674 else
675 if spec.lastIsControlled then
676 SpecializationUtil.raiseEvent(self, "onVehiclePhysicsUpdate", 0, 0, true, 0)
677 end
678 end
679 end
680 end
681
682 -- just a visual update of the steering wheel
683 if self.isClient and isControlled then
684 local allowed = true
685 if spec.idleTurningAllowed then
686 if spec.idleTurningActive and not spec.idleTurningUpdateSteeringWheel then
687 allowed = false
688 end
689 end
690
691 if allowed then
692 self:updateSteeringWheel(spec.steeringWheel, dt, 1)
693 end
694 end
695
696 spec.lastIsControlled = isControlled
697
698 -- steering based on mobile device orientation
699 if self:getIsActiveForInput(true) then
700 local inputHelpMode = g_inputBinding:getInputHelpMode()
701 if inputHelpMode ~= GS_INPUT_HELP_MODE_GAMEPAD or GS_PLATFORM_SWITCH then
702 if g_gameSettings:getValue(GameSettings.SETTING.GYROSCOPE_STEERING) then
703 local dx, dy, dz = getGravityDirection()
704 local steeringValue = MathUtil.getSteeringAngleFromDeviceGravity(dx, dy, dz)
705
706 self:setSteeringInput(steeringValue, true, InputDevice.CATEGORY.WHEEL)
707 end
708 end
709 end
710end

onWriteStream

Description
Called on server side on join
Definition
onWriteStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
329function Drivable:onWriteStream(streamId, connection)
330 local spec = self.spec_drivable
331
332 if spec.cruiseControl.isActive then
333 streamWriteUIntN(streamId, spec.cruiseControl.state, 2)
334 streamWriteUInt8(streamId, spec.cruiseControl.speed)
335 streamWriteUInt8(streamId, spec.cruiseControl.speedReverse)
336 end
337end

onWriteUpdateStream

Description
Called on on update
Definition
onWriteUpdateStream(integer streamId, table connection, integer dirtyMask)
Arguments
integerstreamIdstream ID
tableconnectionconnection
integerdirtyMaskdirty mask
Code
367function Drivable:onWriteUpdateStream(streamId, connection, dirtyMask)
368 local spec = self.spec_drivable
369
370 if streamWriteBool(streamId, bitAND(dirtyMask, spec.dirtyFlag) ~= 0) then
371 local axisForward = (spec.axisForward + 1) / 2 * 1023
372 streamWriteUIntN(streamId, axisForward, 10)
373
374 local axisSide = (spec.axisSide + 1) / 2 * 1023
375 streamWriteUIntN(streamId, axisSide, 10)
376
377 streamWriteBool(streamId, spec.doHandbrake)
378 end
379end

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
26function Drivable.prerequisitesPresent(specializations)
27 return SpecializationUtil.hasSpecialization(Enterable, specializations) and SpecializationUtil.hasSpecialization(Motorized, specializations)
28end

registerEventListeners

Description
Definition
registerEventListeners()
Code
114function Drivable.registerEventListeners(vehicleType)
115 SpecializationUtil.registerEventListener(vehicleType, "onLoad", Drivable)
116 SpecializationUtil.registerEventListener(vehicleType, "onDelete", Drivable)
117 SpecializationUtil.registerEventListener(vehicleType, "onReadStream", Drivable)
118 SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", Drivable)
119 SpecializationUtil.registerEventListener(vehicleType, "onReadUpdateStream", Drivable)
120 SpecializationUtil.registerEventListener(vehicleType, "onWriteUpdateStream", Drivable)
121 SpecializationUtil.registerEventListener(vehicleType, "onUpdate", Drivable)
122 SpecializationUtil.registerEventListener(vehicleType, "onRegisterActionEvents", Drivable)
123 SpecializationUtil.registerEventListener(vehicleType, "onLeaveVehicle", Drivable)
124 SpecializationUtil.registerEventListener(vehicleType, "onSetBroken", Drivable)
125end

registerEvents

Description
Definition
registerEvents()
Code
108function Drivable.registerEvents(vehicleType)
109 SpecializationUtil.registerEvent(vehicleType, "onVehiclePhysicsUpdate")
110end

registerFunctions

Description
Definition
registerFunctions()
Code
70function Drivable.registerFunctions(vehicleType)
71 SpecializationUtil.registerFunction(vehicleType, "updateSteeringWheel", Drivable.updateSteeringWheel)
72 SpecializationUtil.registerFunction(vehicleType, "setCruiseControlState", Drivable.setCruiseControlState)
73 SpecializationUtil.registerFunction(vehicleType, "setCruiseControlMaxSpeed", Drivable.setCruiseControlMaxSpeed)
74 SpecializationUtil.registerFunction(vehicleType, "getCruiseControlState", Drivable.getCruiseControlState)
75 SpecializationUtil.registerFunction(vehicleType, "getCruiseControlSpeed", Drivable.getCruiseControlSpeed)
76 SpecializationUtil.registerFunction(vehicleType, "getCruiseControlMaxSpeed", Drivable.getCruiseControlMaxSpeed)
77 SpecializationUtil.registerFunction(vehicleType, "getCruiseControlDisplayInfo", Drivable.getCruiseControlDisplayInfo)
78 SpecializationUtil.registerFunction(vehicleType, "getAxisForward", Drivable.getAxisForward)
79 SpecializationUtil.registerFunction(vehicleType, "getAccelerationAxis", Drivable.getAccelerationAxis)
80 SpecializationUtil.registerFunction(vehicleType, "getDecelerationAxis", Drivable.getDecelerationAxis)
81 SpecializationUtil.registerFunction(vehicleType, "getCruiseControlAxis", Drivable.getCruiseControlAxis)
82 SpecializationUtil.registerFunction(vehicleType, "getAcDecelerationAxis", Drivable.getAcDecelerationAxis)
83 SpecializationUtil.registerFunction(vehicleType, "getDashboardSteeringAxis", Drivable.getDashboardSteeringAxis)
84 SpecializationUtil.registerFunction(vehicleType, "setReverserDirection", Drivable.setReverserDirection)
85 SpecializationUtil.registerFunction(vehicleType, "getReverserDirection", Drivable.getReverserDirection)
86 SpecializationUtil.registerFunction(vehicleType, "getSteeringDirection", Drivable.getSteeringDirection)
87 SpecializationUtil.registerFunction(vehicleType, "getIsDrivingForward", Drivable.getIsDrivingForward)
88 SpecializationUtil.registerFunction(vehicleType, "getIsDrivingBackward", Drivable.getIsDrivingBackward)
89 SpecializationUtil.registerFunction(vehicleType, "getDrivingDirection", Drivable.getDrivingDirection)
90 SpecializationUtil.registerFunction(vehicleType, "getIsVehicleControlledByPlayer", Drivable.getIsVehicleControlledByPlayer)
91 SpecializationUtil.registerFunction(vehicleType, "updateVehiclePhysics", Drivable.updateVehiclePhysics)
92 SpecializationUtil.registerFunction(vehicleType, "setAccelerationPedalInput", Drivable.setAccelerationPedalInput)
93 SpecializationUtil.registerFunction(vehicleType, "setBrakePedalInput", Drivable.setBrakePedalInput)
94 SpecializationUtil.registerFunction(vehicleType, "setTargetSpeedAndDirection", Drivable.setTargetSpeedAndDirection)
95 SpecializationUtil.registerFunction(vehicleType, "setSteeringInput", Drivable.setSteeringInput)
96 SpecializationUtil.registerFunction(vehicleType, "brakeToStop", Drivable.brakeToStop)
97 SpecializationUtil.registerFunction(vehicleType, "updateSteeringAngle", Drivable.updateSteeringAngle)
98end

registerOverwrittenFunctions

Description
Definition
registerOverwrittenFunctions()
Code
102function Drivable.registerOverwrittenFunctions(vehicleType)
103 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsManualDirectionChangeAllowed", Drivable.getIsManualDirectionChangeAllowed)
104end

saveToXMLFile

Description
Definition
saveToXMLFile()
Code
302function Drivable:saveToXMLFile(xmlFile, key, usedModNames)
303 local spec = self.spec_drivable
304 xmlFile:setValue(key.."#cruiseControl", spec.cruiseControl.speed)
305 xmlFile:setValue(key.."#cruiseControlReverse", spec.cruiseControl.speedReverse)
306end

setAccelerationPedalInput

Description
Definition
setAccelerationPedalInput()
Code
1113function Drivable:setAccelerationPedalInput(inputValue)
1114 local spec = self.spec_drivable
1115 spec.lastInputValues.axisAccelerate = MathUtil.clamp(inputValue, 0, 1)
1116
1117 if spec.lastInputValues.targetSpeed ~= nil then
1118 spec.lastInputValues.targetSpeed = nil
1119 spec.lastInputValues.targetDirection = nil
1120 end
1121end

setBrakePedalInput

Description
Definition
setBrakePedalInput()
Code
1125function Drivable:setBrakePedalInput(inputValue)
1126 local spec = self.spec_drivable
1127 spec.lastInputValues.axisBrake = MathUtil.clamp(inputValue, 0, 1)
1128
1129 if spec.lastInputValues.targetSpeed ~= nil then
1130 spec.lastInputValues.targetSpeed = nil
1131 spec.lastInputValues.targetDirection = nil
1132 end
1133end

setCruiseControlMaxSpeed

Description
Sets cruise control max speed
Definition
setCruiseControlMaxSpeed(float speed, float speedReverse)
Arguments
floatspeednew max speed
floatspeedReversenew max reverse speed
Code
747function Drivable:setCruiseControlMaxSpeed(speed, speedReverse)
748 local spec = self.spec_drivable
749
750 if speed ~= nil then
751 speed = MathUtil.clamp(speed, spec.cruiseControl.minSpeed, spec.cruiseControl.maxSpeed)
752 if spec.cruiseControl.speed ~= speed then
753 spec.cruiseControl.speed = speed
754 if spec.cruiseControl.state == Drivable.CRUISECONTROL_STATE_FULL then
755 spec.cruiseControl.state = Drivable.CRUISECONTROL_STATE_ACTIVE
756 end
757 end
758
759 if speedReverse ~= nil then
760 speedReverse = MathUtil.clamp(speedReverse, spec.cruiseControl.minSpeed, spec.cruiseControl.maxSpeedReverse)
761 spec.cruiseControl.speedReverse = speedReverse
762 end
763
764 if spec.cruiseControl.state ~= Drivable.CRUISECONTROL_STATE_OFF then
765 if spec.cruiseControl.state == Drivable.CRUISECONTROL_STATE_ACTIVE then
766 local speedLimit,_ = self:getSpeedLimit(true)
767 speedLimit = math.min(speedLimit, spec.cruiseControl.speed)
768 self:getMotor():setSpeedLimit(speedLimit)
769 else
770 self:getMotor():setSpeedLimit(math.huge)
771 end
772 end
773
774 if self:getDrivingDirection() < 0 then
775 local speedLimit,_ = self:getSpeedLimit(true)
776 speedLimit = math.min(speedLimit, spec.cruiseControl.speedReverse)
777 self:getMotor():setSpeedLimit(speedLimit)
778 end
779 end
780end

setCruiseControlState

Description
Changes cruise control state
Definition
setCruiseControlState(integer state, boolean noEventSend)
Arguments
integerstatenew state
booleannoEventSendno event send
Code
716function Drivable:setCruiseControlState(state, noEventSend)
717 local spec = self.spec_drivable
718 if spec.cruiseControl ~= nil and spec.cruiseControl.state ~= state then
719 spec.cruiseControl.state = state
720 if noEventSend == nil or not noEventSend then
721 if not self.isServer then
722 g_client:getServerConnection():sendEvent(SetCruiseControlStateEvent.new(self, state))
723 else
724 local owner = self:getOwner()
725 if owner ~= nil then
726 owner:sendEvent(SetCruiseControlStateEvent.new(self, state))
727 end
728 end
729 end
730
731 if spec.toggleCruiseControlEvent ~= nil then
732 local text
733 if state ~= Drivable.CRUISECONTROL_STATE_ACTIVE then
734 text = g_i18n:getText("action_activateCruiseControl")
735 else
736 text = g_i18n:getText("action_deactivateCruiseControl")
737 end
738 g_inputBinding:setActionEventText(spec.toggleCruiseControlEvent, text)
739 end
740 end
741end

setReverserDirection

Description
Definition
setReverserDirection()
Code
924function Drivable:setReverserDirection(reverserDirection)
925 self.spec_drivable.reverserDirection = reverserDirection
926end

setSteeringInput

Description
Definition
setSteeringInput()
Code
1151function Drivable:setSteeringInput(inputValue, isAnalog, deviceCategory)
1152 local spec = self.spec_drivable
1153 spec.lastInputValues.axisSteer = inputValue
1154 if inputValue ~= 0 then
1155 spec.lastInputValues.axisSteerIsAnalog = isAnalog
1156 spec.lastInputValues.axisSteerDeviceCategory = deviceCategory
1157 end
1158end

setTargetSpeedAndDirection

Description
Definition
setTargetSpeedAndDirection()
Code
1137function Drivable:setTargetSpeedAndDirection(speed, direction)
1138 local spec = self.spec_drivable
1139 if direction > 0 then
1140 speed = speed * self:getMotor():getMaximumForwardSpeed() * 3.6
1141 elseif direction < 0 then
1142 speed = speed * self:getMotor():getMaximumBackwardSpeed() * 3.6
1143 end
1144
1145 spec.lastInputValues.targetSpeed = speed
1146 spec.lastInputValues.targetDirection = direction
1147end

stopMotor

Description
Called on motor stop
Definition
stopMotor(boolean noEventSend)
Arguments
booleannoEventSendno event send
Code
980function Drivable:stopMotor(noEventSend)
981 self:setCruiseControlState(Drivable.CRUISECONTROL_STATE_OFF, true)
982end

updateSteeringAngle

Description
Definition
updateSteeringAngle()
Code
1169function Drivable:updateSteeringAngle(wheel, dt, steeringAngle)
1170 local spec = self.spec_drivable
1171 if spec.idleTurningAllowed then
1172 for i=1, #spec.idleTurningWheels do
1173 local wheelData = spec.idleTurningWheels[i]
1174 if wheel.repr == wheel or wheel.driveNode == wheelData.wheelNode then
1175 local idleTurnAngle = wheelData.steeringAngle
1176 if wheelData.inverted then
1177 idleTurnAngle = wheelData.steeringAngle + math.pi
1178 end
1179
1180 return spec.idleTurningActive and idleTurnAngle or steeringAngle
1181 end
1182 end
1183 end
1184
1185 return steeringAngle
1186end

updateSteeringWheel

Description
Definition
updateSteeringWheel()
Code
784function Drivable:updateSteeringWheel(steeringWheel, dt, direction)
785 if steeringWheel ~= nil then
786 local maxRotation = steeringWheel.outdoorRotation
787 if g_currentMission.controlledVehicle == self then
788 if self.getActiveCamera ~= nil then
789 local activeCamera = self:getActiveCamera()
790 if activeCamera ~= nil and activeCamera.isInside then
791 maxRotation = steeringWheel.indoorRotation
792 end
793 end
794 end
795
796 local rotation = self.rotatedTime * maxRotation
797
798 if steeringWheel.lastRotation ~= rotation then
799 steeringWheel.lastRotation = rotation
800
801 setRotation(steeringWheel.node, 0, rotation * direction, 0)
802
803 if self.getVehicleCharacter ~= nil then
804 local vehicleCharacter = self:getVehicleCharacter()
805 if vehicleCharacter ~= nil then
806 if vehicleCharacter:getAllowCharacterUpdate() then
807 vehicleCharacter:setDirty(true)
808 end
809 end
810 end
811 end
812 end
813end

updateVehiclePhysics

Description
Update vehicle physics
Definition
updateVehiclePhysics(float axisForward, boolean axisForwardIsAnalog, float axisSide, boolean axisSideIsAnalog, boolean doHandbrake, float dt)
Arguments
floataxisForwardaxis forward value
booleanaxisForwardIsAnalogforward axis is analog
floataxisSideside axis
booleanaxisSideIsAnalogside axis is analog
booleandoHandbrakedo handbrake
floatdttime since lsat call in ms
Code
1062function Drivable:updateVehiclePhysics(axisForward, axisSide, doHandbrake, dt)
1063 local spec = self.spec_drivable
1064
1065 axisForward = axisForward
1066 axisSide = self:getSteeringDirection() * axisSide
1067
1068 local acceleration = 0
1069
1070 if self:getIsMotorStarted() and self:getMotorStartTime() <= g_currentMission.time then
1071 acceleration = axisForward
1072 if math.abs(acceleration) > 0 then
1073 self:setCruiseControlState(Drivable.CRUISECONTROL_STATE_OFF)
1074 end
1075 if spec.cruiseControl.state ~= Drivable.CRUISECONTROL_STATE_OFF then
1076 acceleration = 1
1077 end
1078 end
1079 if not self:getCanMotorRun() then
1080 acceleration = 0
1081 if self:getIsMotorStarted() then
1082 self:stopMotor()
1083 end
1084 end
1085
1086 -- only update steering if a player is in the vehicle
1087 if self.getIsControlled ~= nil and self:getIsControlled() then
1088 local targetRotatedTime = 0
1089 if self.maxRotTime ~= nil and self.minRotTime ~= nil then
1090 if axisSide < 0 then
1091 -- 0 to maxRotTime
1092 targetRotatedTime = math.min(-self.maxRotTime * axisSide, self.maxRotTime)
1093 else
1094 -- 0 to minRotTime
1095 targetRotatedTime = math.max(self.minRotTime * axisSide, self.minRotTime)
1096 end
1097 end
1098
1099 self.rotatedTime = targetRotatedTime
1100 end
1101
1102 if self.finishedFirstUpdate then
1103 if self.spec_wheels ~= nil and #self.spec_wheels.wheels > 0 then
1104 WheelsUtil.updateWheelsPhysics(self, dt, self.lastSpeedReal*self.movingDirection, acceleration, doHandbrake, g_currentMission.missionInfo.stopAndGoBraking)
1105 end
1106 end
1107
1108 return acceleration
1109end