LUADOC - Farming Simulator 17

Printable Version

Script v1.4.4.0

Engine v7.0.0.2

Foundation Reference

Leveler

Description
Class for all Levelers
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
17function Leveler.prerequisitesPresent(specializations)
18 return SpecializationUtil.hasSpecialization(Fillable, specializations);
19end

load

Description
Called on loading
Definition
load(table savegame)
Arguments
tablesavegamesavegame
Code
30function Leveler:load(savegame)
31
32 self.leveler = {};
33
34 self.leveler.pickUpDirection = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.leveler.pickUpDirection"), 1.0);
35
36
37 self.leveler.nodes = {};
38
39 local i=0;
40 while true do
41 local key = string.format("vehicle.leveler.levelerNode(%d)", i);
42 if not hasXMLProperty(self.xmlFile, key) then
43 break;
44 end
45
46 local levelerNode = {};
47 if self:loadLevelerNodeFromXML(levelerNode, self.xmlFile, key) then
48 table.insert(self.leveler.nodes, levelerNode);
49 end;
50
51 table.insert(self.leveler.nodes, levelerNode);
52
53 i=i+1;
54 end
55
56 self.leveler.fillUnitIndex = getXMLInt(self.xmlFile, "vehicle.leveler#fillUnitIndex");
57
58 if self.isClient then
59 self.leveler.effects = EffectManager:loadEffect(self.xmlFile, "vehicle.levelerEffects", self.components, self);
60 for i,effect in pairs(self.leveler.effects) do
61 if effect.node ~= nil then
62 effect.speed = Utils.getNoNil(getXMLFloat(self.xmlFile, string.format("vehicle.levelerEffects.effectNode(%d)#speed", i-1)), 1) * 0.001;
63 effect.maxHeight = Utils.getNoNil(getXMLFloat(self.xmlFile, string.format("vehicle.levelerEffects.effectNode(%d)#maxHeight", i-1)), 1);
64 effect.scrollPosition = 0;
65 effect.depthTarget = 0;
66 end
67 end
68 end
69
70end

update

Description
Called on update
Definition
update(float dt)
Arguments
floatdttime since last call in ms
Code
96function Leveler:update(dt)
97 if self:getIsActive() then
98 if self.isClient then
99 local fillType = self:getUnitFillType(self.leveler.fillUnitIndex);
100 local visible = self:getUnitFillLevel(self.leveler.fillUnitIndex) > 2*TipUtil.getMinValidLiterValue(fillType);
101 if visible and fillType ~= FillUtil.FILLTYPE_UNKNOWN then
102 EffectManager:setFillType(self.leveler.effects, fillType)
103 EffectManager:startEffects(self.leveler.effects);
104
105 local fillPercentage =self:getUnitFillLevel(self.leveler.fillUnitIndex) / self:getUnitCapacity(self.leveler.fillUnitIndex);
106
107 for _,effect in pairs(self.leveler.effects) do
108 if effect.depthTarget ~= nil then
109
110 if effect.depthTarget < fillPercentage then
111 effect.depthTarget = math.min(fillPercentage, effect.depthTarget + 0.001*dt);
112 elseif effect.depthTarget > fillPercentage then
113 effect.depthTarget = math.max(fillPercentage, effect.depthTarget - 0.001*dt);
114 end
115
116 local speed = self.movingDirection * effect.speed * self:getLastSpeed();
117 effect.scrollPosition = effect.scrollPosition + speed;
118
119 setShaderParameter(effect.node, "VertxoffsetVertexdeformMotionUVscale", effect.maxHeight, effect.depthTarget, effect.scrollPosition, 6.0, false);
120
121 setVisibility(effect.node, true);
122 end
123 end
124 else
125 EffectManager:stopEffects(self.leveler.effects);
126 for _,effect in pairs(self.leveler.effects) do
127 if effect.node ~= nil then
128 effect.depthTarget = 0;
129 effect.scrollPosition = 0;
130 setVisibility(effect.node, false);
131 end
132 end
133 end
134 end
135 end
136
137 if self:getIsActive() and self.isServer then
138
139 local fillFactor = 1;
140 local emptyFactor = 1;
141
142 for _,levelerNode in pairs(self.leveler.nodes) do
143
144 local pickedUpFillLevel = 0;
145
146 local fillType = self:getUnitFillType(self.leveler.fillUnitIndex);
147 local fillLevel = self:getUnitFillLevel(self.leveler.fillUnitIndex);
148
149 if fillType == FillUtil.FILLTYPE_UNKNOWN or fillLevel < TipUtil.getMinValidLiterValue(fillType) + 0.001 then
150 local x0,y0,z0 = localToWorld(levelerNode.node, -levelerNode.width, 0, 0.5*levelerNode.maxDropDirOffset);
151 local x1,y1,z1 = localToWorld(levelerNode.node, levelerNode.width, 0, 0.5*levelerNode.maxDropDirOffset);
152
153 local newFillType = TipUtil.getFillTypeAtLine(x0,y0,z0, x1,y1,z1, 0.5*levelerNode.maxDropDirOffset);
154 if newFillType ~= FillUtil.FILLTYPE_UNKNOWN and newFillType ~= fillType then
155 self:setUnitFillLevel(self.leveler.fillUnitIndex, 0);
156 fillType = newFillType;
157 end
158 end
159 local heightType = TipUtil.fillTypeToHeightType[fillType];
160
161
162 if fillType ~= FillUtil.FILLTYPE_UNKNOWN and heightType ~= nil then
163
164 local innerRadius = 0;
165 local outerRadius = TipUtil.getDefaultMaxRadius(fillType);
166
167 -- use occlusion areas only, if they are close to the ground
168 local tipOcclusionAreas = {};
169 -- temporary disabled
170 --for _,area in pairs(self.tipOcclusionAreas) do
171 -- local xs,ys,zs = getWorldTranslation(area.start);
172 -- local xw,yw,zw = getWorldTranslation(area.width);
173 -- local xh,yh,zh = getWorldTranslation(area.height);
174 --
175 -- local x1 = xs + 0.5*(xh - xs);
176 -- local y1 = ys + 0.5*(yh - ys);
177 -- local z1 = zs + 0.5*(zh - zs);
178 --
179 -- local x2 = xw + 0.5*(xh - xs);
180 -- local y2 = yw + 0.5*(yh - ys);
181 -- local z2 = zw + 0.5*(zh - zs);
182 --
183 -- local h1 = TipUtil.getHeightAtWorldPos(x1,y1,z1);
184 -- local h2 = TipUtil.getHeightAtWorldPos(x2,y2,z2);
185 --
186 -- if h1 > y1 - 0.5 and h2 > y2 - 0.5 then
187 -- table.insert(tipOcclusionAreas, area);
188 -- end
189 --end
190
191 local capacity = self:getUnitCapacity(self.leveler.fillUnitIndex);
192
193 -- pick up at node
194 if self:getIsLevelerPickupNodeActive(levelerNode) then
195 if self.leveler.pickUpDirection == self.movingDirection then
196 local sx,sy,sz = localToWorld(levelerNode.node, -levelerNode.width, 0, 0);
197 local ex,ey,ez = localToWorld(levelerNode.node, levelerNode.width, 0, 0);
198
199 local fillLevel = self:getUnitFillLevel(self.leveler.fillUnitIndex);
200 local delta = -fillFactor * (capacity-fillLevel);
201 local numHeightLimitChecks = levelerNode.numHeightLimitChecks;
202 if numHeightLimitChecks > 0 then
203 local movementY = 0;
204 for i=0,numHeightLimitChecks do
205 local t = i/numHeightLimitChecks
206 local xi = sx + (ex-sx)*t;
207 local yi = sy + (ey-sy)*t;
208 local zi = sz + (ez-sz)*t;
209 local hi = TipUtil.getHeightAtWorldPos(xi,yi,zi);
210 movementY = math.max(movementY, hi-0.05 - yi); -- limit to 5cm below surface
211 end
212 if movementY > 0 then
213 sy = sy+movementY;
214 ey = ey+movementY;
215 end
216 end
217
218 levelerNode.lastPickUp, levelerNode.lineOffsetPickUp = TipUtil.tipToGroundAroundLine(self, delta, fillType, sx,sy-0.1,sz, ex,ey-0.1,ez, innerRadius, outerRadius, levelerNode.lineOffsetPickUp, true, nil);
219
220 if levelerNode.lastPickUp < 0 then
221 self:setUnitFillLevel(self.leveler.fillUnitIndex, fillLevel - levelerNode.lastPickUp, fillType, nil, nil);
222 pickedUpFillLevel = levelerNode.lastPickUp;
223 end
224 end
225 end
226
227 -- drop at node
228 local fillLevel = self:getUnitFillLevel(self.leveler.fillUnitIndex);
229 if fillLevel > 0 then
230 local f = (fillLevel/capacity);
231 local width = Utils.lerp(levelerNode.minDropWidth, levelerNode.maxDropWidth, f);
232
233 local sx,sy,sz = localToWorld(levelerNode.node, -width, 0, 0);
234 local ex,ey,ez = localToWorld(levelerNode.node, width, 0, 0);
235
236 local delta = math.min(fillLevel, emptyFactor * fillLevel);
237 local yOffset = -0.1 -0.05;
238
239 levelerNode.lastDrop1, levelerNode.lineOffsetDrop1 = TipUtil.tipToGroundAroundLine(self, delta, fillType, sx,sy+yOffset,sz, ex,ey+yOffset,ez, innerRadius, outerRadius, levelerNode.lineOffsetDrop1, true, tipOcclusionAreas);
240 if levelerNode.lastDrop1 > 0 then
241 self:setUnitFillLevel(self.leveler.fillUnitIndex, fillLevel - levelerNode.lastDrop1, fillType, nil, nil);
242 end
243 end
244
245 -- drop further at front
246 local fillLevel = self:getUnitFillLevel(self.leveler.fillUnitIndex);
247
248 if fillLevel > 0 then
249 local f = (fillLevel/capacity);
250 local width = Utils.lerp(levelerNode.minDropWidth, levelerNode.maxDropWidth, f);
251
252 local yOffset = Utils.lerp(levelerNode.minDropHeight, levelerNode.maxDropHeight, f);
253
254 local delta = math.min(fillLevel, emptyFactor * fillLevel);
255
256 local sx,sy,sz = localToWorld(levelerNode.node, -width, 0, 0);
257 local ex,ey,ez = localToWorld(levelerNode.node, width, 0, 0);
258 local dx,dy,dz = localDirectionToWorld(levelerNode.node, 0, 0, 1);
259
260 local backOffset = -outerRadius * self.leveler.pickUpDirection * 1.5;
261 local backLen = Utils.lerp(levelerNode.minDropDirOffset, levelerNode.maxDropDirOffset, f) - backOffset;
262
263 local backX,backY,backZ = dx*backOffset,dy*backOffset,dz*backOffset;
264 dx,dy,dz = dx*backLen,dy*backLen,dz*backLen;
265
266
267 addDensityMapHeightOcclusionArea(TipUtil.terrainDetailHeightUpdater, sx+backX,sy+backY,sz+backZ, ex-sx,ey-sy,ez-sz, dx, dy, dz, true);
268 if width < levelerNode.width-0.05 then
269 -- fully block left and right of the inner block area
270 local sx2,sy2,sz2 = localToWorld(levelerNode.node, -levelerNode.width, 0, 0);
271 local ex2,ey2,ez2 = localToWorld(levelerNode.node, levelerNode.width, 0, 0);
272
273 addDensityMapHeightOcclusionArea(TipUtil.terrainDetailHeightUpdater, sx2+backX,sy2+backY,sz2+backZ, sx-sx2,sy-sy2,sz-sz2, dx, dy, dz, false);
274 addDensityMapHeightOcclusionArea(TipUtil.terrainDetailHeightUpdater, ex +backX,ey +backY,ez +backZ, ex2-ex,ey2-ey,ez2-ez, dx, dy, dz, false);
275 end
276
277
278 levelerNode.lastDrop2, levelerNode.lineOffsetDrop2 = TipUtil.tipToGroundAroundLine(self, delta, fillType, sx,sy+yOffset,sz, ex,ey+yOffset,ez, 0, outerRadius, levelerNode.lineOffsetDrop2, true, tipOcclusionAreas);
279 if levelerNode.lastDrop2 > 0 then
280 self:setUnitFillLevel(self.leveler.fillUnitIndex, fillLevel - levelerNode.lastDrop2, fillType, nil, nil);
281 end
282
283 end
284
285 end
286
287 if pickedUpFillLevel < 0 and fillType ~= FillUtil.FILLTYPE_UNKNOWN then
288 if self.changedFillLevelCallback ~= nil then
289 if self.changedFillLevelCallbackTarget ~= nil then
290 self.changedFillLevelCallback(self.changedFillLevelCallbackTarget, self, pickedUpFillLevel, fillType)
291 else
292 self.changedFillLevelCallback(self, pickedUpFillLevel, fillType)
293 end
294 end
295 end
296
297 end
298
299 end
300end

loadLevelerNodeFromXML

Description
Loads leveler node from xml
Definition
loadLevelerNodeFromXML(table levelerNode, integer xmlFile, string key)
Arguments
tablelevelerNodeleveler node data
integerxmlFileid of xml object
stringkeykey
Return Values
booleansuccesssuccess
Code
314function Leveler:loadLevelerNodeFromXML(superFunc, levelerNode, xmlFile, key)
315 levelerNode.node = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key .. "#index"));
316 if levelerNode.node ~= nil then
317 --levelerNode.fillUnitIndex = getXMLInt(self.xmlFile, key .. "#fillUnitIndex");
318 levelerNode.width = getXMLFloat(self.xmlFile, key .. "#width");
319
320 levelerNode.minDropWidth = Utils.getNoNil(getXMLFloat(self.xmlFile, key .. "#minDropWidth"), levelerNode.width*0.5);
321 levelerNode.maxDropWidth = Utils.getNoNil(getXMLFloat(self.xmlFile, key .. "#maxDropWidth"), levelerNode.width);
322 levelerNode.minDropHeight = Utils.getNoNil(getXMLFloat(self.xmlFile, key .. "#minDropHeight"), 0);
323 levelerNode.maxDropHeight = Utils.getNoNil(getXMLFloat(self.xmlFile, key .. "#maxDropHeight"), 1);
324 levelerNode.minDropDirOffset = Utils.getNoNil(getXMLFloat(self.xmlFile, key .. "#minDropDirOffset"), 0.7);
325 levelerNode.maxDropDirOffset = Utils.getNoNil(getXMLFloat(self.xmlFile, key .. "#maxDropDirOffset"), 0.7);
326 levelerNode.numHeightLimitChecks = Utils.getNoNil(getXMLFloat(self.xmlFile, key .. "#numHeightLimitChecks"), 6);
327
328 levelerNode.lineOffsetPickUp = nil;
329 levelerNode.lineOffsetDrop = nil;
330
331 levelerNode.lastPickUp = 0;
332 levelerNode.lastDrop = 0;
333
334 if superFunc ~= nil then
335 return superFunc(self, levelerNode, xmlFile, key);
336 end
337
338 return true
339 end
340 return false;
341end;

getIsLevelerPickupNodeActive

Description
Returns true if leveler pickup node is active
Definition
getIsLevelerPickupNodeActive(table levelerNode)
Arguments
tablelevelerNodepickup node data
Return Values
booleanisActivepickup node is active
Code
347function Leveler:getIsLevelerPickupNodeActive(superFunc, levelerNode)
348 if superFunc ~= nil then
349 return superFunc(self, levelerNode)
350 end
351 return true
352end

setChangedFillLevelCallback

Description
Set fill level changed callback (e.g. by bunker silo)
Definition
setChangedFillLevelCallback(function callback, table callbackTarget)
Arguments
functioncallbackcallback
tablecallbackTargetcallback target
Code
358function Leveler:setChangedFillLevelCallback(callback, callbackTarget)
359 self.changedFillLevelCallback = callback;
360 self.changedFillLevelCallbackTarget = callbackTarget;
361end