LUADOC - Farming Simulator 17

Printable Version

Script v1.4.4.0

Engine v7.0.0.2

Foundation Reference

CrabSteering

Description
Class for vehicles with variable steering modes
Functions

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
22function CrabSteering.prerequisitesPresent(specializations)
23 return SpecializationUtil.hasSpecialization(Drivable, specializations);
24end

load

Description
Called on loading
Definition
load(table savegame)
Arguments
tablesavegamesavegame
Code
29function CrabSteering:load(savegame)
30 self.setCrabSteering = SpecializationUtil.callSpecializationsFunction("setCrabSteering");
31
32 self.updateSteeringAngle = CrabSteering.updateSteeringAngle;
33 self.updateArticulatedAxisRotation = CrabSteering.updateArticulatedAxisRotation
34
35 self.crabSteering = {};
36 self.crabSteering.state = 1;
37 self.crabSteering.stateMax = -1;
38
39 self.crabSteering.distFromCompJointToCenterOfBackWheels = getXMLFloat(self.xmlFile, "vehicle.crabSteering#distFromCompJointToCenterOfBackWheels");
40 self.crabSteering.aiSteeringModeIndex = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.crabSteering#aiSteeringModeIndex"), 1);
41 self.crabSteering.toggleSpeedFactor = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.crabSteering#toggleSpeedFactor"), 1);
42
43 self.crabSteeringCheckedInputs = {};
44 table.insert(self.crabSteeringCheckedInputs, InputBinding.TOGGLE_CRABSTEERING);
45
46 local baseKey = "vehicle.crabSteering";
47
48 self.crabSteering.steeringModes = {};
49 local i=0;
50 while true do
51 local key = string.format("%s.steeringMode(%d)", baseKey, i);
52 if not hasXMLProperty(self.xmlFile, key) then
53 break;
54 end
55 local entry = {};
56 entry.name = g_i18n:getText( getXMLString(self.xmlFile, key .. "#name") );
57
58 local inputBindingName = getXMLString(self.xmlFile, key .. "#inputBindingName");
59 if inputBindingName ~= nil then
60 if InputBinding[inputBindingName] ~= nil then
61 entry.inputBinding = InputBinding[inputBindingName];
62 end
63 end
64
65 entry.wheels = {};
66 local j=0;
67 while true do
68 local wheelKey = string.format("%s.wheel(%d)", key, j);
69 if not hasXMLProperty(self.xmlFile, wheelKey) then
70 break;
71 end
72 local wheelEntry = {};
73 wheelEntry.wheelIndex = getXMLInt(self.xmlFile, wheelKey .. "#index");
74 wheelEntry.offset = math.rad( Utils.getNoNil(getXMLFloat(self.xmlFile, wheelKey .. "#offset"), 0) );
75 wheelEntry.locked = Utils.getNoNil(getXMLBool(self.xmlFile, wheelKey .. "#locked"), false);
76
77 if self.wheels[wheelEntry.wheelIndex] ~= nil then
78 self.wheels[wheelEntry.wheelIndex].steeringOffset = 0;
79
80 self.wheels[wheelEntry.wheelIndex].rotSpeedBackUp = self.wheels[wheelEntry.wheelIndex].rotSpeed;
81 else
82 print("Error: CrabSteering, the wheelIndex '"..tostring(wheelEntry.wheelIndex).."' is not valid!");
83 end
84
85 table.insert(entry.wheels, wheelEntry);
86 j=j+1;
87 end
88
89 if self.articulatedAxis ~= nil then
90 self.articulatedAxis.currentOffset = 0;
91 self.articulatedAxis.rotSpeedBackUp = self.articulatedAxis.rotSpeed;
92 entry.articulatedAxis = {};
93 entry.articulatedAxis.offset = math.rad( Utils.getNoNil(getXMLFloat(self.xmlFile, key .. ".articulatedAxis(0)#offset"), 0) );
94 entry.articulatedAxis.locked = Utils.getNoNil(getXMLBool(self.xmlFile, key .. ".articulatedAxis(0)#locked"), false);
95 local vector = { Utils.getVectorFromString(getXMLString(self.xmlFile, key .. ".articulatedAxis(0)#wheelIndices")) };
96 if vector[1] ~= nil then
97 entry.articulatedAxis.wheelIndices = vector;
98 end
99 end
100
101 entry.animations = {};
102 local j=0;
103 while true do
104 local animKey = string.format("%s.animation(%d)", key, j);
105 if not hasXMLProperty(self.xmlFile, animKey) then
106 break;
107 end
108 local animName = getXMLString(self.xmlFile, animKey .. "#name");
109 local animSpeed = Utils.getNoNil(getXMLFloat(self.xmlFile, animKey .. "#speed"), 1.0);
110 local stopTime = getXMLFloat(self.xmlFile, animKey .. "#stopTime");
111 if animName ~= nil and self.animations[animName] ~= nil then
112 table.insert(entry.animations, {animName=animName, animSpeed=animSpeed, stopTime=stopTime});
113 end
114 j=j+1;
115 end
116
117 table.insert(self.crabSteering.steeringModes, entry);
118 i=i+1;
119 end
120 self.crabSteering.stateMax = table.getn(self.crabSteering.steeringModes);
121 if self.crabSteering.stateMax > ((2^CrabSteering.STEERING_SEND_NUM_BITS) - 1) then
122 print("Error: CrabSteering only supports "..((2^CrabSteering.STEERING_SEND_NUM_BITS) - 1).." steering modes!");
123 end
124
125 if self.crabSteering.stateMax > 0 then
126 self:setCrabSteering(1, true);
127 end
128end

readStream

Description
Called on client side on join
Definition
readStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
137function CrabSteering:readStream(streamId, connection)
138 if self.crabSteering.stateMax == 0 then
139 return;
140 end
141 self.crabSteering.state = streamReadUIntN(streamId, CrabSteering.STEERING_SEND_NUM_BITS);
142end

writeStream

Description
Called on server side on join
Definition
writeStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
148function CrabSteering:writeStream(streamId, connection)
149 if self.crabSteering.stateMax == 0 then
150 return;
151 end
152 streamWriteUIntN(streamId, self.crabSteering.state, CrabSteering.STEERING_SEND_NUM_BITS);
153end

readUpdateStream

Description
Called on on update
Definition
readUpdateStream(integer streamId, integer timestamp, table connection)
Arguments
integerstreamIdstream ID
integertimestamptimestamp
tableconnectionconnection
Code
160function CrabSteering:readUpdateStream(streamId, timestamp, connection)
161 if self.crabSteering.stateMax == 0 then
162 return;
163 end
164 if self.articulatedAxis ~= nil then
165 self.articulatedAxis.curRot = streamReadFloat32(streamId);
166 end
167end

writeUpdateStream

Description
Called on on update
Definition
writeUpdateStream(integer streamId, table connection, integer dirtyMask)
Arguments
integerstreamIdstream ID
tableconnectionconnection
integerdirtyMaskdirty mask
Code
174function CrabSteering:writeUpdateStream(streamId, connection, dirtyMask)
175 if self.crabSteering.stateMax == 0 then
176 return;
177 end
178 if self.articulatedAxis ~= nil then
179 streamWriteFloat32(streamId, self.articulatedAxis.curRot);
180 end
181end

update

Description
Called on update
Definition
update(float dt)
Arguments
floatdttime since last call in ms
Code
192function CrabSteering:update(dt)
193 if self.crabSteering.stateMax == 0 then
194 return;
195 end
196 if self:getIsActive() then
197 -- input
198 if self.crabSteering.stateMax > 0 and self:getIsActiveForInput(false) and not self:hasInputConflictWithSelection(self.crabSteeringCheckedInputs) then
199 local state = self.crabSteering.state;
200 if InputBinding.hasEvent(InputBinding.TOGGLE_CRABSTEERING) then
201 state = state + 1;
202 if state > self.crabSteering.stateMax then
203 state = 1;
204 end
205 else
206 for i,mode in pairs(self.crabSteering.steeringModes) do
207 if mode.inputBinding ~= nil then
208 if InputBinding.hasEvent(mode.inputBinding) then
209 state = i;
210 break;
211 end
212 end
213 end
214 end
215 if state ~= self.crabSteering.state then
216 self:setCrabSteering(state);
217 end
218 end
219 end
220end

draw

Description
Called on draw
Definition
draw()
Code
224function CrabSteering:draw()
225 if self.crabSteering.stateMax == 0 then
226 return;
227 end
228 if self:getIsActive() then
229 if self.crabSteering.stateMax > 0 and self:getIsActiveForInput(false) and not self:hasInputConflictWithSelection(self.crabSteeringCheckedInputs) then
230 local mode = self.crabSteering.steeringModes[self.crabSteering.state];
231 g_currentMission:addHelpButtonText(mode.name, InputBinding.TOGGLE_CRABSTEERING);
232 end
233 end
234end

setCrabSteering

Description
Change crap steering mode
Definition
setCrabSteering(integer state, boolean noEventSend)
Arguments
integerstatenew state
booleannoEventSendno event send
Code
243function CrabSteering:setCrabSteering(state, noEventSend)
244 if noEventSend == nil or noEventSend == false then
245 if g_server ~= nil then
246 g_server:broadcastEvent(SetCrabSteeringEvent:new(self, state), nil, nil, self);
247 else
248 g_client:getServerConnection():sendEvent(SetCrabSteeringEvent:new(self, state));
249 end
250 end
251
252 if state ~= self.crabSteering.state then
253 local currentMode = self.crabSteering.steeringModes[self.crabSteering.state];
254 if currentMode.animations ~= nil then
255 for _,anim in pairs(currentMode.animations) do
256 local curTime = self:getAnimationTime(anim.animName);
257 if anim.stopTime == nil then
258 self:playAnimation(anim.animName, -anim.animSpeed, curTime, noEventSend);
259 end
260 end
261 end
262 local newMode = self.crabSteering.steeringModes[state];
263 if newMode.animations ~= nil then
264 for _,anim in pairs(newMode.animations) do
265 local curTime = self:getAnimationTime(anim.animName);
266 if anim.stopTime ~= nil then
267 self:setAnimationStopTime(anim.animName, anim.stopTime);
268 local speed = 1.0;
269 if curTime > anim.stopTime then
270 speed = -1.0;
271 end
272 self:playAnimation(anim.animName, speed, curTime, noEventSend);
273 else
274 self:playAnimation(anim.animName, anim.animSpeed, curTime, noEventSend);
275 end
276 end
277 end
278 end
279
280 self.crabSteering.state = state;
281end

onStartAiVehicle

Description
Called on start ai vehicle
Definition
onStartAiVehicle()
Code
285function CrabSteering:onStartAiVehicle()
286 if self.crabSteering.stateMax > 0 then
287 self:setCrabSteering(self.crabSteering.aiSteeringModeIndex, true);
288 end
289end

onStopAiVehicle

Description
Called on stop ai vehicle
Definition
onStopAiVehicle()
Code
293function CrabSteering:onStopAiVehicle()
294end

updateSteeringAngle

Description
Update steering angle depending of the selected steering mode
Definition
updateSteeringAngle(table wheel, float dt, float steeringAngle)
Arguments
tablewheelwheel
floatdttime since last call in ms
floatsteeringAnglesteering angle
Return Values
floatsteeringAngleadjusted steering angle
Code
302function CrabSteering:updateSteeringAngle(wheel, dt, steeringAngle)
303 if self.crabSteering.stateMax == 0 then
304 return steeringAngle;
305 end
306
307 local currentMode = self.crabSteering.steeringModes[self.crabSteering.state];
308 if currentMode.wheels == nil or table.getn(currentMode.wheels) == 0 then
309 return steeringAngle;
310 end
311
312 for k,wheelProperties in pairs(currentMode.wheels) do
313 if self.wheels[wheelProperties.wheelIndex] == wheel then --and (wheel.rotSpeed ~= 0 or wheel.rotSpeedBackUp ~= nil) then
314
315 local rotScale = math.min(1.0/(self.lastSpeed*self.speedRotScale+self.speedRotScaleOffset), 1);
316 local delta = dt*0.001*self.autoRotateBackSpeed*rotScale * self.crabSteering.toggleSpeedFactor;
317
318 if wheel.steeringOffset < wheelProperties.offset then
319 wheel.steeringOffset = math.min(wheelProperties.offset, wheel.steeringOffset + delta);
320 elseif wheel.steeringOffset > wheelProperties.offset then
321 wheel.steeringOffset = math.max(wheelProperties.offset, wheel.steeringOffset - delta);
322 end
323
324
325 if not wheelProperties.locked then
326
327 local rotSpeed = 0;
328
329 if self.rotatedTime > 0 then
330 rotSpeed = (wheel.rotMax - wheel.steeringOffset) / self.wheelSteeringDuration;
331 if wheel.rotSpeedBackUp < 0 then
332 rotSpeed = (wheel.rotMin - wheel.steeringOffset) / self.wheelSteeringDuration;
333 end
334 else
335 rotSpeed = -(wheel.rotMin - wheel.steeringOffset) / self.wheelSteeringDuration;
336 if wheel.rotSpeedBackUp < 0 then
337 rotSpeed = -(wheel.rotMax - wheel.steeringOffset) / self.wheelSteeringDuration;
338 end
339 end
340
341 if wheel.rotSpeed < wheel.rotSpeedBackUp then
342 wheel.rotSpeed = math.min(wheel.rotSpeedBackUp, wheel.rotSpeed + delta);
343 elseif wheel.rotSpeed > wheel.rotSpeedBackUp then
344 wheel.rotSpeed = math.max(wheel.rotSpeedBackUp, wheel.rotSpeed - delta);
345 end
346 local f = wheel.rotSpeed / wheel.rotSpeedBackUp;
347
348 steeringAngle = wheel.steeringOffset + (self.rotatedTime * f * rotSpeed);
349
350 else
351
352 if wheel.steeringAngle > wheel.steeringOffset or steeringAngle > wheel.steeringOffset then
353 steeringAngle = math.max(wheel.steeringOffset, math.min(wheel.steeringAngle, steeringAngle) - delta);
354 elseif wheel.steeringAngle < wheel.steeringOffset or steeringAngle < wheel.steeringOffset then
355 steeringAngle = math.min(wheel.steeringOffset, math.max(wheel.steeringAngle, steeringAngle) + delta);
356 end
357
358 if steeringAngle == wheel.steeringOffset then
359 wheel.rotSpeed = 0;
360 else
361 if wheel.rotSpeed < 0 then
362 wheel.rotSpeed = math.min(0, wheel.rotSpeed + delta);
363 elseif wheel.rotSpeed > 0 then
364 wheel.rotSpeed = math.max(0, wheel.rotSpeed - delta);
365 end
366 end
367
368 end
369
370 steeringAngle = Utils.clamp(steeringAngle, wheel.rotMin, wheel.rotMax);
371
372 break;
373 end
374 end
375
376 return steeringAngle;
377end

updateArticulatedAxisRotation

Description
Update articulated axis rotation
Definition
updateArticulatedAxisRotation(float steeringAngle, float dt)
Arguments
floatsteeringAnglesteering angle
floatdttime since last call in ms
Return Values
floatsteeringAngleadjusted steering angle
Code
384function CrabSteering:updateArticulatedAxisRotation(steeringAngle, dt)
385 if self.crabSteering.stateMax == 0 then
386 return steeringAngle;
387 end
388
389 if not self.isServer then
390 return self.articulatedAxis.curRot;
391 end
392
393 local currentMode = self.crabSteering.steeringModes[self.crabSteering.state];
394 if currentMode.articulatedAxis == nil then
395 return steeringAngle;
396 end
397
398 --
399 local rotScale = math.min(1.0/(self.lastSpeed*self.speedRotScale+self.speedRotScaleOffset), 1);
400 local delta = dt*0.001*self.autoRotateBackSpeed*rotScale * self.crabSteering.toggleSpeedFactor;
401
402 if self.articulatedAxis.currentOffset < currentMode.articulatedAxis.offset then
403 self.articulatedAxis.currentOffset = math.min(currentMode.articulatedAxis.offset, self.articulatedAxis.currentOffset + delta);
404 elseif self.articulatedAxis.currentOffset > currentMode.articulatedAxis.offset then
405 self.articulatedAxis.currentOffset = math.max(currentMode.articulatedAxis.offset, self.articulatedAxis.currentOffset - delta);
406 end
407
408 -- adjust rotSpeed
409 if currentMode.articulatedAxis.locked then
410 if self.articulatedAxis.rotSpeed > 0 then
411 self.articulatedAxis.rotSpeed = math.max(0, self.articulatedAxis.rotSpeed - delta);
412 elseif self.articulatedAxis.rotSpeed < 0 then
413 self.articulatedAxis.rotSpeed = math.min(0, self.articulatedAxis.rotSpeed + delta);
414 end
415 else
416 if self.articulatedAxis.rotSpeed > self.articulatedAxis.rotSpeedBackUp then
417 self.articulatedAxis.rotSpeed = math.max(self.articulatedAxis.rotSpeedBackUp, self.articulatedAxis.rotSpeed - delta);
418 elseif self.articulatedAxis.rotSpeed < self.articulatedAxis.rotSpeedBackUp then
419 self.articulatedAxis.rotSpeed = math.min(self.articulatedAxis.rotSpeedBackUp, self.articulatedAxis.rotSpeed + delta);
420 end
421 end
422
423
424 local rotSpeed = 0;
425 if (self.rotatedTime) * (self.articulatedAxis.rotSpeedBackUp) > 0 then
426 rotSpeed = (self.articulatedAxis.rotMax - self.articulatedAxis.currentOffset) / self.wheelSteeringDuration;
427 else
428 rotSpeed = (self.articulatedAxis.rotMin - self.articulatedAxis.currentOffset) / self.wheelSteeringDuration;
429 end
430
431 local f = math.abs(self.articulatedAxis.rotSpeed) / math.abs(self.articulatedAxis.rotSpeedBackUp);
432 rotSpeed = rotSpeed * f;
433
434 steeringAngle = self.articulatedAxis.currentOffset + (math.abs(self.rotatedTime) * rotSpeed);
435
436
437
438 -- optimize rotation if cutter is lowered
439 local adjustedRotation = false;
440 local cutterObject = next(self.attachedCutters);
441 if cutterObject ~= nil then
442 adjustedRotation = cutterObject:isLowered(false);
443 end
444
445 if adjustedRotation and currentMode.articulatedAxis.wheelIndices ~= nil and self.crabSteering.distFromCompJointToCenterOfBackWheels ~= nil then
446 local curRot = Utils.sign(self.articulatedAxis.rotSpeedBackUp) * self.articulatedAxis.curRot;
447
448 local alpha = 0;
449 local count = 0;
450 for _,wheelIndex in pairs(currentMode.articulatedAxis.wheelIndices) do
451 alpha = alpha + self.wheels[wheelIndex].steeringAngle;
452 count = count + 1;
453 end;
454 alpha = alpha / count;
455 alpha = alpha - curRot;
456
457 local v = 0;
458 local count = 0;
459 for _,wheelIndex in pairs(currentMode.articulatedAxis.wheelIndices) do
460 local wheel = self.wheels[wheelIndex];
461 local axleSpeed = getWheelShapeAxleSpeed(wheel.node, wheel.wheelShape); -- rad/sec
462 if wheel.hasGroundContact then
463 local longSlip, latSlip = getWheelShapeSlip(wheel.node, wheel.wheelShape);
464 local fac = 1.0 - math.min(1.0, longSlip);
465 v = v + fac * axleSpeed * wheel.radius;
466 count = count + 1;
467 end
468 end;
469 v = v / count;
470 local h = v * 0.001 * dt;
471 local g = math.sin(alpha) * h;
472 local a = math.cos(alpha) * h;
473 local ls = self.crabSteering.distFromCompJointToCenterOfBackWheels;
474 local beta = math.atan2(g, ls - a);
475
476 steeringAngle = Utils.sign(self.articulatedAxis.rotSpeedBackUp) * (curRot + beta);
477
478 end
479
480 steeringAngle = math.max(self.articulatedAxis.rotMin, math.min(self.articulatedAxis.rotMax, steeringAngle));
481
482 return steeringAngle;
483end