![Hi :hi:](./images/smilies/hi.gif)
Ich möchte beim Krone EasyFlow, dem Aufsammler für den Krone Häcksler, den Gras Ertrag einstellen.
Leider finde ich in den Lua keinen Wert dafür.
Würde mich über hilfe freuen
![Wink ;)](./images/smilies/icon_wink.gif)
![]() | ![]() | ![]() |
![]() | -- -- EasyFlow -- This is the specialization for EasyFlow -- It reacts both to steerable and attachable events -- -- @author Stefan Geiger -- @date 04/12/08 -- -- -- Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved. -- -- -- @coAuthor Milan Lekše [milan1702976] -- @date 18/02/13 -- -- -- Copyright (C) http://www.FS-UK.com, Confidential, All Rights Reserved. EasyFlow = {}; function EasyFlow.prerequisitesPresent(specializations) return true; end; function EasyFlow:load(xmlFile) self.onStartReel = SpecializationUtil.callSpecializationsFunction("onStartReel"); self.onStopReel = SpecializationUtil.callSpecializationsFunction("onStopReel"); --self.setFruitType = SpecializationUtil.callSpecializationsFunction("setFruitType"); self.getCombine = EasyFlow.getCombine; self.applyInitialAnimation = Utils.overwrittenFunction(self.applyInitialAnimation, EasyFlow.applyInitialAnimation); self.getDirectionSnapAngle = Utils.overwrittenFunction(self.getDirectionSnapAngle, EasyFlow.getDirectionSnapAngle); self.reelNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.reel#index")); self.reelSpeed = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.reel#speed"), 0.003); self.reelSpeedScale = 1; self.rollNodes = {}; local rollNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.roll#index")); if rollNode ~= nil then local speed = 0.003*3; table.insert(self.rollNodes, {node=rollNode, speed=speed}); end; local i = 0; while true do local key = string.format("vehicle.rolls.roll(%d)", i); if not hasXMLProperty(xmlFile, key) then break; end; local rollNode = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#index")); local speed = Utils.getNoNil(getXMLFloat(xmlFile, key.."#speed"), 0.003); if rollNode ~= nil then table.insert(self.rollNodes, {node=rollNode, speed=speed}); end; i = i + 1; end; local indexSpikesStr = getXMLString(xmlFile, "vehicle.reelspikes#index"); self.spikesCount = getXMLInt(xmlFile, "vehicle.reelspikes#count"); self.spikesRootNode = Utils.indexToObject(self.components, indexSpikesStr); self.sideArm = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.sidearms#index")); self.sideArmMovable = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.sidearms#movable"), false); self.cutterStartAnimation = getXMLString(xmlFile, "vehicle.cutterStartAnimation#name"); self.cutterStartAnimationSpeedScale = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.cutterStartAnimation#speedScale"), 1); self.cutterStartAnimationInitialIsStarted = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.cutterStartAnimation#initialIsStarted"), false); self.cutterAllowCuttingWhileRaised = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.cutterAllowCuttingWhileRaised"), false); self.cutterSpeedRotatingParts = {}; local i=0; while true do local baseName = string.format("vehicle.cutterSpeedRotatingParts.cutterSpeedRotatingPart(%d)", i); local index = getXMLString(xmlFile, baseName.. "#index"); if index == nil then break; end; local node = Utils.indexToObject(self.components, index); if node ~= nil then local entry = {}; entry.node = node; entry.rotationSpeedScale = getXMLFloat(xmlFile, baseName.."#rotationSpeedScale"); if entry.rotationSpeedScale == nil then entry.rotationSpeedScale = 1.0/Utils.getNoNil(getXMLFloat(xmlFile, baseName.."#radius"), 1); end; entry.foldMinLimit = Utils.getNoNil(getXMLFloat(xmlFile, baseName .. "#foldMinLimit"), 0); entry.foldMaxLimit = Utils.getNoNil(getXMLFloat(xmlFile, baseName .. "#foldMaxLimit"), 1); table.insert(self.cutterSpeedRotatingParts, entry); end; i = i+1; end; self.threshingParticleSystems = {}; local psName = "vehicle.threshingParticleSystem"; Utils.loadParticleSystem(xmlFile, self.threshingParticleSystems, psName, self.components, false, nil, self.baseDirectory) self.fruitExtraObjects = {}; local i = 0; while true do local key = string.format("vehicle.fruitExtraObjects.fruitExtraObject(%d)", i); local t = getXMLString(xmlFile, key.."#fruitType"); local index = getXMLString(xmlFile, key.."#index"); if t==nil or index==nil then break; end; local node = Utils.indexToObject(self.components, index); if node ~= nil then if self.currentExtraObject == nil then self.currentExtraObject = node; setVisibility(node, true); else setVisibility(node, false); end; self.fruitExtraObjects[t] = node; end; i = i +1; end; self.cutterThreshingUVScrollParts = {}; local i = 0; while true do local key = string.format("vehicle.cutterThreshingUVScrollParts.cutterThreshingUVScrollPart(%d)", i); if not hasXMLProperty(xmlFile, key) then break; end; local node = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#index")); local speed = Utils.getVectorNFromString(getXMLString(xmlFile, key.."#speed"), 2); if node ~= nil and speed then table.insert(self.cutterThreshingUVScrollParts, {node=node, speed=speed}); end; i = i +1; end; self.preferedCombineSize = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.preferedCombineSize"), 1); self.fruitTypes = {}; local fruitTypes = getXMLString(xmlFile, "vehicle.fruitTypes#fruitTypes"); if fruitTypes ~= nil then local types = Utils.splitString(" ", fruitTypes); for k,v in pairs(types) do local desc = FruitUtil.fruitTypes[v]; if desc ~= nil then self.fruitTypes[desc.index] = true; end; end; end; self.convertedFruits = {}; local i = 0; while true do local key = string.format("vehicle.convertedFruits.convertedFruit(%d)", i); if not hasXMLProperty(xmlFile, key) then break; end; local inputType = getXMLString(xmlFile, key .. "#input"); local outputType = getXMLString(xmlFile, key .. "#output"); if inputType ~= nil and outputType ~= nil then local inputDesc = FruitUtil.fruitTypes[inputType]; local outputDesc = FruitUtil.fruitTypes[outputType]; if inputDesc ~= nil and outputDesc ~= nil then self.convertedFruits[inputDesc.index] = outputDesc.index; end; end; i = i + 1; end; self.cutterMovingDirection = Utils.sign(Utils.getNoNil(getXMLInt(xmlFile, "vehicle.cutterMovingDirection"), -1)); self.currentInputFruitType = FruitUtil.FRUITTYPE_UNKNOWN; self.reelStarted = false; self.forceLowSpeed = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.cutterSpeedLimit#forceLow"), false); self.speedLimitLow = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.cutterSpeedLimit#low"), 12); self.speedLimit = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.cutterSpeedLimit#normal"), 25.5); self.speedViolationMaxTime = 50; self.speedViolationTimer = self.speedViolationMaxTime; self.lastCutterArea = 0; self.lastCutterAreaBiggerZero = self.lastCutterArea > 0; self.cutterGroundFlag = self:getNextDirtyFlag(); self.aiLeftCheck = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.aiLeftCheck#index")); self.aiRightCheck = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.aiRightCheck#index")); self.dtSum = 0; end; function EasyFlow:applyInitialAnimation(superFunc) if self.cutterStartAnimation ~= nil and self.playAnimation ~= nil and self.cutterStartAnimationInitialIsStarted then self:playAnimation(self.cutterStartAnimation, -self.cutterStartAnimationSpeedScale, nil, true); AnimatedVehicle.updateAnimations(self, 99999999); end if superFunc ~= nil then superFunc(self); end end function EasyFlow:delete() Utils.deleteParticleSystem(self.threshingParticleSystems); end; function EasyFlow:readStream(streamId, timestamp, connection) self.lastCutterAreaBiggerZero = streamReadBool(streamId); end; function EasyFlow:writeStream(streamId, connection, dirtyMask) streamWriteBool(streamId, self.lastCutterAreaBiggerZero); end; function EasyFlow:readUpdateStream(streamId, timestamp, connection) if connection:getIsServer() then self.lastCutterAreaBiggerZero = streamReadBool(streamId); end; end; function EasyFlow:writeUpdateStream(streamId, connection, dirtyMask) if not connection:getIsServer() then streamWriteBool(streamId, self.lastCutterAreaBiggerZero); end; end; function EasyFlow:mouseEvent(posX, posY, isDown, isUp, button) end; function EasyFlow:keyEvent(unicode, sym, modifier, isDown) end; function EasyFlow:update(dt) Utils.setEmittingState(self.threshingParticleSystems, (self.reelStarted and self.lastCutterAreaBiggerZero)); if self.reelStarted then for _, rollNode in pairs(self.rollNodes) do rotate(rollNode.node, -dt*rollNode.speed, 0, 0); end; if self.reelNode ~= nil then rotate(self.reelNode, -dt*self.reelSpeed*self.reelSpeedScale, 0, 0); if self.sideArmMovable then --:TODO: move arm downwards end; --correct spikes, so that they always look down local atx, aty, atz = getRotation(self.reelNode); for i=1, self.spikesCount do local spike = getChildAt(self.spikesRootNode, i-1); --local tx, ty, tz = getRotation(spike); setRotation(spike, -atx, aty, atz); end; end; end; end; function EasyFlow.updateAIMovement(self, dt) if not self:getIsAIThreshingAllowed() then self:stopAIThreshing(); return; end; if not self.isControlled then if g_currentMission.environment.needsLights then self:setLightsVisibility(true); else self:setLightsVisibility(false); end; end; local allowedToDrive = true; if self.grainTankCapacity == 0 then if not self.pipeStateIsUnloading[self.currentPipeState] then allowedToDrive = false; end if not self.isPipeUnloading and (self.lastArea > 0 or self.lastLostGrainTankFillLevel > 0) then -- there is some fruit to unload, but there is no trailer. Stop and wait for a trailer self.waitingForTrailerToUnload = true; end; else if self.grainTankFillLevel >= self.grainTankCapacity then allowedToDrive = false; end end if self.waitingForTrailerToUnload then if self.lastValidGrainTankFruitType ~= FruitUtil.FRUITTYPE_UNKNOWN then local trailer = self:findTrailerToUnload(self.lastValidGrainTankFruitType); if trailer ~= nil then -- there is a trailer to unload. Continue working self.waitingForTrailerToUnload = false; end; else -- we did not cut anything yet. We shouldn't have ended in this state. Just continue working self.waitingForTrailerToUnload = false; end; end; if (self.grainTankFillLevel >= self.grainTankCapacity and self.grainTankCapacity > 0) or self.waitingForTrailerToUnload or self.waitingForDischarge then allowedToDrive = false; end; for _,v in pairs(self.numCollidingVehicles) do if v > 0 then allowedToDrive = false; break; end; end; if self.turnStage > 0 then if self.waitForTurnTime > self.time or (self.pipeIsUnloading and self.turnStage < 3) then allowedToDrive = false; end; end; if not self:getIsThreshingAllowed(true) then allowedToDrive = false; self:setIsThreshing(false); self.waitingForWeather = true; else if self.waitingForWeather then if self.turnStage == 0 then self.driveBackTime = self.time + self.driveBackTimeout; end; self:startThreshing(); self.waitingForWeather = false; end; end; if not allowedToDrive then --local x,y,z = getWorldTranslation(self.aiTreshingDirectionNode); --local lx, lz = 0, 1; --AIVehicleUtil.getDriveDirection(self.aiTreshingDirectionNode, self.aiThreshingTargetX, y, self.aiThreshingTargetZ); --AIVehicleUtil.driveInDirection(self, dt, 30, 0, 0, 28, false, moveForwards, lx, lz) AIVehicleUtil.driveInDirection(self, dt, 30, 0, 0, 28, false, moveForwards, nil, nil) return; end; local speedLevel = 2; local leftMarker = self.aiLeftMarker; local rightMarker = self.aiRightMarker; local hasFruitPreparer = false; local fruitType = self.lastValidInputFruitType; if self.fruitPreparerFruitType ~= nil and self.fruitPreparerFruitType == fruitType then hasFruitPreparer = true; end for cutter,implement in pairs(self.attachedCutters) do if cutter.aiLeftMarker ~= nil and leftMarker == nil then leftMarker = cutter.aiLeftMarker; end; if cutter.aiRightMarker ~= nil and rightMarker == nil then rightMarker = cutter.aiRightMarker; end; if Cutter.getUseLowSpeedLimit(cutter) then speedLevel = 1; end; end; if leftMarker == nil or rightMarker == nil then self:stopAIThreshing(); return; end; if self.driveBackTime >= self.time then local x,y,z = getWorldTranslation(self.aiTreshingDirectionNode); local lx, lz = AIVehicleUtil.getDriveDirection(self.aiTreshingDirectionNode, self.aiThreshingTargetX, y, self.aiThreshingTargetZ); AIVehicleUtil.driveInDirection(self, dt, 30, 0, 0, 28, true, false, lx, lz, speedLevel, 1) return; end; local hasArea = true; if self.lastArea < 1 then local x,y,z = getWorldTranslation(self.aiTreshingDirectionNode); local dirX, dirZ = self.aiThreshingDirectionX, self.aiThreshingDirectionZ; local lInX, lInY, lInZ = getWorldTranslation(leftMarker); local rInX, rInY, rInZ = getWorldTranslation(rightMarker); local heightX = lInX + dirX * self.frontAreaSize; local heightZ = lInZ + dirZ * self.frontAreaSize; -- local area = Utils.getFruitArea(fruitType, lInX, lInZ, rInX, rInZ, heightX, heightZ, hasFruitPreparer); local area = EasyFlow.getFruitWindrowArea(fruitType, lInX, lInZ, rInX, rInZ, heightX, heightZ); if area < 1 then hasArea = false; end; end; if hasArea then self.turnTimer = self.turnTimeout; else self.turnTimer = self.turnTimer - dt; end; local newTargetX, newTargetY, newTargetZ; local moveForwards = true; local updateWheels = true; self.moveForwards = false if self.turnTimer < 0 or (self.turnStage > 0 or self.turnStage < 0) then if self.turnStage > 0 then local x,y,z = getWorldTranslation(self.aiTreshingDirectionNode); local dirX, dirZ = self.aiThreshingDirectionX, self.aiThreshingDirectionZ; local myDirX, myDirY, myDirZ = localDirectionToWorld(self.aiTreshingDirectionNode, 0, 0, 1); newTargetX = self.aiThreshingTargetX; newTargetY = y; newTargetZ = self.aiThreshingTargetZ; if self.turnStage == 1 then self.turnStageTimer = self.turnStageTimer - dt; if self.lastSpeed < self.aiRescueSpeedThreshold then self.aiRescueTimer = self.aiRescueTimer - dt; else self.aiRescueTimer = self.aiRescueTimeout; end; if myDirX*dirX + myDirZ*dirZ > self.turnStage1AngleCosThreshold or self.turnStageTimer < 0 or self.aiRescueTimer < 0 then self.turnStage = 2; moveForwards = false; if self.turnStageTimer < 0 or self.aiRescueTimer < 0 then self.aiThreshingTargetBeforeSaveX = self.aiThreshingTargetX; self.aiThreshingTargetBeforeSaveZ = self.aiThreshingTargetZ; newTargetX = self.aiThreshingTargetBeforeTurnX; newTargetZ = self.aiThreshingTargetBeforeTurnZ; moveForwards = false; self.turnStage = 4; self.turnStageTimer = self.turnStage4Timeout; else self.turnStageTimer = self.turnStage2Timeout; end; self.aiRescueTimer = self.aiRescueTimeout; end; elseif self.turnStage == 2 then self.turnStageTimer = self.turnStageTimer - dt; if self.lastSpeed < self.aiRescueSpeedThreshold then self.aiRescueTimer = self.aiRescueTimer - dt; else self.aiRescueTimer = self.aiRescueTimeout; end; if (myDirX*dirX + myDirZ*dirZ > self.turnStage2AngleCosThreshold or self.turnStageTimer < 0 or self.aiRescueTimer < 0) or self.skipTurnStage2 == true then AICombine.switchToTurnStage3(self); else moveForwards = false; end; elseif self.turnStage == 3 then --[[if Utils.vector2Length(x-newTargetX, z-newTargetZ) < self.turnEndDistance then self.turnTimer = self.turnTimeoutLong; self.turnStage = 0; --print("turning done"); end;]] if self.lastSpeed < self.aiRescueSpeedThreshold then self.aiRescueTimer = self.aiRescueTimer - dt; else self.aiRescueTimer = self.aiRescueTimeout; end; local dx, dz = x-newTargetX, z-newTargetZ; local dot = dx*dirX + dz*dirZ; if -dot < self.turnEndDistance then self.turnTimer = self.turnTimeoutLong; self.turnStage = 0; elseif self.aiRescueTimer < 0 then self.aiThreshingTargetBeforeSaveX = self.aiThreshingTargetX; self.aiThreshingTargetBeforeSaveZ = self.aiThreshingTargetZ; newTargetX = self.aiThreshingTargetBeforeTurnX; newTargetZ = self.aiThreshingTargetBeforeTurnZ; moveForwards = false; self.turnStage = 4; self.turnStageTimer = self.turnStage4Timeout; end; elseif self.turnStage == 4 then self.turnStageTimer = self.turnStageTimer - dt; if self.lastSpeed < self.aiRescueSpeedThreshold then self.aiRescueTimer = self.aiRescueTimer - dt; else self.aiRescueTimer = self.aiRescueTimeout; end; if self.aiRescueTimer < 0 then self.aiRescueTimer = self.aiRescueTimeout; local x,y,z = localDirectionToWorld(self.aiRescueNode, 0, 0, -1); local scale = self.aiRescueForce/Utils.vector2Length(x,z); addForce(self.aiRescueNode, x*scale, 0, z*scale, 0, 0, 0, true); end; if self.turnStageTimer < 0 then self.aiRescueTimer = self.aiRescueTimeout; self.turnStageTimer = self.turnStage1Timeout; self.turnStage = 1; newTargetX = self.aiThreshingTargetBeforeSaveX; newTargetZ = self.aiThreshingTargetBeforeSaveZ; else local dirX, dirZ = -dirX, -dirZ; -- just drive along direction local targetX, targetZ = self.aiThreshingTargetX, self.aiThreshingTargetZ; local dx, dz = x-targetX, z-targetZ; local dot = dx*dirX + dz*dirZ; local projTargetX = targetX +dirX*dot; local projTargetZ = targetZ +dirZ*dot; newTargetX = projTargetX-dirX*self.lookAheadDistance; newTargetZ = projTargetZ-dirZ*self.lookAheadDistance; moveForwards = false; end; end; elseif fruitType == FruitUtil.FRUITTYPE_UNKNOWN then self:stopAIThreshing(); return; else -- turn local x,y,z = getWorldTranslation(self.aiTreshingDirectionNode); local lx,ly,lz = nil, nil, nil local rx,ry,rz = nil, nil, nil local dirX, dirZ = self.aiThreshingDirectionX, self.aiThreshingDirectionZ; local sideX, sideZ = -dirZ, dirX; local lInX, lInY, lInZ = getWorldTranslation(leftMarker); local rInX, rInY, rInZ = getWorldTranslation(rightMarker); local threshWidth = Utils.vector2Length(lInX-rInX, lInZ-rInZ); local leftFruit = 0 local rightFruit = 0 local turnLeft = true; local mythreshWidth = 0.51 local mySideWatchDirOffset = -1.01 local mySideWatchDirSize = 2.01 local doBreak = false for transXDouble=0,30 do local transX = transXDouble * 0.5 for transZ=-6,14 do setTranslation(self.aiLeftCheck, transX*-1,-0.5,transZ) setTranslation(self.aiRightCheck, transX*1,-0.5,transZ) lx,ly,lz = getWorldTranslation(self.aiLeftCheck); rx,ry,rz = getWorldTranslation(self.aiRightCheck); lWidthX = lx - sideX*0.5*mythreshWidth + dirX * mySideWatchDirOffset lWidthZ = lz - sideZ*0.5*mythreshWidth + dirZ * mySideWatchDirOffset lStartX = lWidthX - sideX*0.7*mythreshWidth lStartZ = lWidthZ - sideZ*0.7*mythreshWidth lHeightX = lStartX + dirX* mySideWatchDirSize lHeightZ = lStartZ + dirZ* mySideWatchDirSize rWidthX = rx + sideX*0.5*mythreshWidth + dirX * mySideWatchDirOffset rWidthZ = rz + sideZ*0.5*mythreshWidth + dirZ * mySideWatchDirOffset rStartX = rWidthX + sideX*0.7*mythreshWidth rStartZ = rWidthZ + sideZ*0.7*mythreshWidth rHeightX = rStartX + dirX* mySideWatchDirSize rHeightZ = rStartZ + dirZ* mySideWatchDirSize testLeftFruit = EasyFlow.getFruitWindrowArea(fruitType, lStartX, lStartZ, lWidthX, lWidthZ, lHeightX, lHeightZ); testRightFruit = EasyFlow.getFruitWindrowArea(fruitType, rStartX, rStartZ, rWidthX, rWidthZ, rHeightX, rHeightZ); if (testLeftFruit > 5 and testLeftFruit > leftFruit) or (testRightFruit > 5 and testRightFruit > rightFruit) then if transZ < 6 then self.moveForwards = true if transX < 1 then self.turnTimer = self.turnTimeout; end end if transX > 5 then self.skipTurnStage2 = true else self.skipTurnStage2 = false end leftFruit = testLeftFruit rightFruit = testRightFruit if transX < 1 then setTranslation(self.aiLeftCheck, (transX+threshWidth)*-1,-0.5,transZ) setTranslation(self.aiRightCheck, (transX+threshWidth)*1,-0.5,transZ) lx,ly,lz = getWorldTranslation(self.aiLeftCheck); rx,ry,rz = getWorldTranslation(self.aiRightCheck); else setTranslation(self.aiLeftCheck, (transX+threshWidth*0.6)*-1,-0.5,transZ) setTranslation(self.aiRightCheck, (transX+threshWidth*0.6)*1,-0.5,transZ) lx,ly,lz = getWorldTranslation(self.aiLeftCheck); rx,ry,rz = getWorldTranslation(self.aiRightCheck); end doBreak = true break end end if doBreak == true then break end end if self.moveForwards == true then if self.turnTimer > 0 then self.turnStage = 0 self:setAIImplementsMoveDown(true); else self.turnStage = -1 self:setAIImplementsMoveDown(false); end -- do not turn jet local x,y,z = getWorldTranslation(self.aiTreshingDirectionNode); local dirX, dirZ = self.aiThreshingDirectionX, self.aiThreshingDirectionZ; -- just drive along direction local targetX, targetZ = self.aiThreshingTargetX, self.aiThreshingTargetZ; local dx, dz = x-targetX, z-targetZ; local dot = dx*dirX + dz*dirZ; local projTargetX = targetX +dirX*dot; local projTargetZ = targetZ +dirZ*dot; --print("old target: "..targetX.." ".. targetZ .. " distOnDir " .. dot.." proj: "..projTargetX.." "..projTargetZ); newTargetX = projTargetX+self.aiThreshingDirectionX*self.lookAheadDistance; newTargetY = y; newTargetZ = projTargetZ+self.aiThreshingDirectionZ*self.lookAheadDistance; --print(distOnDir.." target: "..newTargetX.." ".. newTargetZ); else if leftFruit > 0 or rightFruit > 0 then if leftFruit > rightFruit then turnLeft = true; else turnLeft = false; end else self:stopAIThreshing(); return; end; -- turn to where more fruit is to cut local targetX, targetZ = self.aiThreshingTargetX, self.aiThreshingTargetZ; --local dx, dz = x-targetX, z-targetZ; --local dot = dx*dirX + dz*dirZ; --local x, z = targetX + dirX*dot, targetZ + dirZ*dot; --threshWidth = threshWidth*self.aiTurnThreshWidthScale; local markerSideOffset; if turnLeft then markerSideOffset, _, _ = worldToLocal(self.aiTreshingDirectionNode, lx,ly,lz); else markerSideOffset, _, _ = worldToLocal(self.aiTreshingDirectionNode, rx,ry,rz); end local myAiTurnThreshWidthMaxDifference = 0.6 local areaOverlap = math.min(threshWidth*(1-self.aiTurnThreshWidthScale), myAiTurnThreshWidthMaxDifference); if markerSideOffset > 0 then markerSideOffset = math.max(markerSideOffset - areaOverlap, 0.01); else markerSideOffset = math.min(markerSideOffset + areaOverlap, -0.01); end local x,z = Utils.projectOnLine(x, z, targetX, targetZ, dirX, dirZ) newTargetX = x-sideX*markerSideOffset; newTargetY = y; newTargetZ = z-sideZ*markerSideOffset; self.aiThreshingDirectionX = -dirX; self.aiThreshingDirectionZ = -dirZ; self.turnStage = 1; self.aiRescueTimer = self.aiRescueTimeout; self.turnStageTimer = self.turnStage1Timeout; self.aiThreshingTargetBeforeTurnX = self.aiThreshingTargetX; self.aiThreshingTargetBeforeTurnZ = self.aiThreshingTargetZ; self.waitForTurnTime = self.time + self.waitForTurnTimeout; self:setAIImplementsMoveDown(false); -- do not thresh while turning self.allowsThreshing = false; updateWheels = false if turnLeft then --print("turning left ", threshWidth); else --print("turning right ", threshWidth); end; end end; else local x,y,z = getWorldTranslation(self.aiTreshingDirectionNode); local dirX, dirZ = self.aiThreshingDirectionX, self.aiThreshingDirectionZ; -- just drive along direction local targetX, targetZ = self.aiThreshingTargetX, self.aiThreshingTargetZ; local dx, dz = x-targetX, z-targetZ; local dot = dx*dirX + dz*dirZ; local projTargetX = targetX +dirX*dot; local projTargetZ = targetZ +dirZ*dot; --print("old target: "..targetX.." ".. targetZ .. " distOnDir " .. dot.." proj: "..projTargetX.." "..projTargetZ); newTargetX = projTargetX+self.aiThreshingDirectionX*self.lookAheadDistance; newTargetY = y; newTargetZ = projTargetZ+self.aiThreshingDirectionZ*self.lookAheadDistance; --print(distOnDir.." target: "..newTargetX.." ".. newTargetZ); end; if updateWheels then local lx, lz = AIVehicleUtil.getDriveDirection(self.aiTreshingDirectionNode, newTargetX, newTargetY, newTargetZ); if self.turnStage == 2 and math.abs(lx) < 0.1 then AICombine.switchToTurnStage3(self); moveForwards = true; end; AIVehicleUtil.driveInDirection(self, dt, 25, 0.5, 0.5, 20, true, moveForwards, lx, lz, speedLevel, 0.9); --local maxAngle = 0.785398163; --45?; local maxlx = 0.7071067; --math.sin(maxAngle); local colDirX = lx; local colDirZ = lz; if colDirX > maxlx then colDirX = maxlx; colDirZ = 0.7071067; --math.cos(maxAngle); elseif colDirX < -maxlx then colDirX = -maxlx; colDirZ = 0.7071067; --math.cos(maxAngle); end; for triggerId,_ in pairs(self.numCollidingVehicles) do AIVehicleUtil.setCollisionDirection(self.aiTreshingDirectionNode, triggerId, colDirX, colDirZ); end; end; self.aiThreshingTargetX = newTargetX; self.aiThreshingTargetZ = newTargetZ; end; function EasyFlow.getFruitWindrowArea(fruitId, startWorldX, startWorldZ, widthWorldX, widthWorldZ, heightWorldX, heightWorldZ) local ids = g_currentMission.fruits[fruitId]; if ids == nil or ids.windrowId == 0 then return 0, 0; end local id = ids.windrowId; local x,z, widthX,widthZ, heightX,heightZ = Utils.getXZWidthAndHeight(id, startWorldX, startWorldZ, widthWorldX, widthWorldZ, heightWorldX, heightWorldZ); local ret, _, total = getDensityParallelogram(id, x, z, widthX, widthZ, heightX, heightZ, 0, g_currentMission.numWindrowChannels); return ret, total; end function EasyFlow:updateTick(dt) if self.isServer then self.lastCutterArea = 0; self.lastCutterAreaBiggerZero = false; local combineAI = self:getCombine(); if combineAI ~= nil then if combineAI.aiLeftCheck == nil or combineAI.aiRightCheck == nil then combineAI.aiLeftCheck = self.aiLeftCheck combineAI.aiRightCheck = self.aiRightCheck end if combineAI.isAIThreshing then if combineAI.isBroken or combineAI.aiLeftCheck == nil or combineAI.aiRightCheck == nil then combineAI:stopAIThreshing(); end; combineAI.dtSum = - 1000 self.dtSum = self.dtSum + dt; if self.dtSum > 50 then EasyFlow.updateAIMovement(combineAI, self.dtSum); self.dtSum = 0; end; end end end; if self.reelStarted and self.movingDirection == self.cutterMovingDirection and (self.cutterAllowCuttingWhileRaised or self:isLowered(true)) then local speedLimit = self.speedLimit; if EasyFlow.getUseLowSpeedLimit(self) then speedLimit = self.speedLimitLow; end if self:doCheckSpeedLimit() and self.lastSpeed*3600 > speedLimit then self.speedViolationTimer = self.speedViolationTimer - dt; else self.speedViolationTimer = self.speedViolationMaxTime; end local oldInputFruitType = self.currentInputFruitType; if self.isServer then if self.speedViolationTimer > 0 then local combine = self:getCombine(); if combine ~= nil and combine:getIsThreshingAllowed(false) and combine.allowsThreshing then local cuttingAreasSend = {}; for _,area in pairs(self.cuttingAreas) do if self:getIsAreaActive(area) then local x,_,z = getWorldTranslation(area.start); local x1,_,z1 = getWorldTranslation(area.width); local x2,_,z2 = getWorldTranslation(area.height); table.insert(cuttingAreasSend, {x,z,x1,z1,x2,z2}); end; end; if (table.getn(cuttingAreasSend) > 0) then for fruitType,_ in pairs(self.fruitTypes) do local outputFruitType = fruitType; if self.convertedFruits[fruitType] ~= nil then outputFruitType = self.convertedFruits[fruitType]; end; if combine:getIsCutterFruitTypeAllowed(outputFruitType) then local lastCutterArea, realArea = EasyFlowAreaEvent.runLocally(cuttingAreasSend, fruitType); if lastCutterArea > 0 then self.currentInputFruitType = fruitType; self.lastCutterArea = lastCutterArea; self.lastCutterAreaBiggerZero = (self.lastCutterArea > 0); combine:addCutterArea(self, lastCutterArea, realArea, fruitType, outputFruitType); g_server:broadcastEvent(EasyFlowAreaEvent:new(cuttingAreasSend, fruitType)); if self.lastCutterAreaBiggerZero ~= self.lastCutterAreaBiggerZeroSent then self:raiseDirtyFlags(self.cutterGroundFlag); self.lastCutterAreaBiggerZeroSent = self.lastCutterAreaBiggerZero; end; local pixelToSqm = g_currentMission:getFruitPixelsToSqm(); -- 4096px are mapped to 2048m local sqm = realArea*pixelToSqm; local ha = sqm/10000; g_currentMission.missionStats.hectaresThreshedTotal = g_currentMission.missionStats.hectaresThreshedTotal + ha; g_currentMission.missionStats.hectaresThreshedSession = g_currentMission.missionStats.hectaresThreshedSession + ha; -- Stop the loop over all fruit types break; end end end end end end else local combine = self:getCombine(); if combine ~= nil and combine.lastValidInputFruitType ~= FruitUtil.FRUITTYPE_UNKNOWN then self.currentInputFruitType = combine.lastValidInputFruitType; end end if self.currentInputFruitType ~= oldInputFruitType then EasyFlow.updateExtraObjects(self); end if self:isLowered(true) then local foldAnimTime = self.foldAnimTime; for k,v in pairs(self.cutterSpeedRotatingParts) do if foldAnimTime == nil or (foldAnimTime <= v.foldMaxLimit and foldAnimTime >= v.foldMinLimit) then rotate(v.node, v.rotationSpeedScale * self.lastSpeedReal * self.movingDirection * dt, 0, 0); end end end else self.speedViolationTimer = self.speedViolationMaxTime; end end function EasyFlow:draw() end; function EasyFlow:onDetach() if self.deactivateOnDetach then EasyFlow.onDeactivate(self); end; end; function EasyFlow:onLeave() if self.deactivateOnLeave then EasyFlow.onDeactivate(self); end; end; function EasyFlow:onDeactivate() self:onStopReel(); Utils.setEmittingState(self.threshingParticleSystems, false); self.speedViolationTimer = self.speedViolationMaxTime; end; function EasyFlow:setReelSpeedSpace(speedScale) self.reelSpeedScale = speedScale; end; function EasyFlow:onStartReel() self.reelStarted = true; for _, part in pairs(self.cutterThreshingUVScrollParts) do setShaderParameter(part.node, "uvScrollSpeed", part.speed[1], part.speed[2], 0, 0, false); end; if self.cutterStartAnimation ~= nil and self.playAnimation ~= nil then self:playAnimation(self.cutterStartAnimation, self.cutterStartAnimationSpeedScale, nil, true); end end; function EasyFlow:onStopReel() self.reelStarted = false; Utils.setEmittingState(self.threshingParticleSystems, false); self.speedViolationTimer = self.speedViolationMaxTime; for _, part in pairs(self.cutterThreshingUVScrollParts) do setShaderParameter(part.node, "uvScrollSpeed", 0, 0, 0, 0, false); end; if self.cutterStartAnimation ~= nil and self.playAnimation ~= nil then self:playAnimation(self.cutterStartAnimation, -self.cutterStartAnimationSpeedScale, nil, true); end end; function EasyFlow:getDirectionSnapAngle(superFunc) local snapAngle = 0; for fruitType,_ in pairs(self.fruitTypes) do local desc = FruitUtil.fruitIndexToDesc[fruitType]; if desc ~= nil then snapAngle = math.max(snapAngle, desc.directionSnapAngle); end end return math.max(snapAngle, superFunc(self)); end function EasyFlow:getCombine() if self.getIsThreshingAllowed ~= nil and self.getIsCutterFruitTypeAllowed ~= nil and self.grainTankFillLevel ~= nil then return self; else local c = self.attacherVehicle; if c ~= nil and c.getIsThreshingAllowed ~= nil and c.getIsCutterFruitTypeAllowed ~= nil and c.grainTankFillLevel ~= nil then return c; end end; return nil; end --[[function EasyFlow:resetFruitType() self.currentFruitType = FruitUtil.FRUITTYPE_UNKNOWN; self.currentInputFruitType = FruitUtil.FRUITTYPE_UNKNOWN; self.lastCutterArea = 0; end;]] --[[function EasyFlow:setFruitType(fruitType) if self.currentInputFruitType ~= fruitType then self.currentInputFruitType = fruitType; self.currentFruitType = fruitType; if self.convertedFruits[fruitType] ~= nil then self.currentFruitType = self.convertedFruits[fruitType]; end; self.lastCutterArea = 0; EasyFlow.updateExtraObjects(self) end; end;]] function EasyFlow.getUseLowSpeedLimit(self) local combineSize = self.combineSize; if combineSize == nil then if self.attacherVehicle ~= nil then combineSize = self.attacherVehicle.combineSize; end end if self.forceLowSpeed or (combineSize ~= nil and self.preferedCombineSize > combineSize) then return true; end return false; end; function EasyFlow.updateExtraObjects(self) if self.currentExtraObject ~= nil then setVisibility(self.currentExtraObject, false); self.currentExtraObject = nil; end; if self.currentInputFruitType ~= FruitUtil.FRUITTYPE_UNKNOWN then local name = FruitUtil.fruitIndexToDesc[self.currentInputFruitType].name; local extraObject = self.fruitExtraObjects[name]; if extraObject ~= nil then setVisibility(extraObject, true); self.currentExtraObject = extraObject; end; end; end; | ![]() |
![]() | ![]() | ![]() |
![]() | ![]() | ![]() |
![]() | -- Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved. EasyFlowAreaEvent = {}; EasyFlowAreaEvent_mt = Class(EasyFlowAreaEvent, Event); InitEventClass(EasyFlowAreaEvent, "EasyFlowAreaEvent"); function EasyFlowAreaEvent:emptyNew() local self = Event:new(EasyFlowAreaEvent_mt); return self; end; function EasyFlowAreaEvent:new(cuttingAreas, fruitType) local self = EasyFlowAreaEvent:emptyNew() self.cuttingAreas = cuttingAreas; self.fruitType = fruitType; return self; end; function EasyFlowAreaEvent:readStream(streamId, connection) local numAreas = streamReadUIntN(streamId, 4); local fruitType = streamReadUIntN(streamId, FruitUtil.sendNumBits); local params = g_currentMission.areaCompressionParams; local paramsRelative = g_currentMission.areaRelativeCompressionParams; for i=1, numAreas do local x = Utils.readCompressedWorldPosition(streamId, params); local z = Utils.readCompressedWorldPosition(streamId, params); local x1 = x + Utils.readCompressedWorldPosition(streamId, paramsRelative); local z1 = z + Utils.readCompressedWorldPosition(streamId, paramsRelative); local x2 = x + Utils.readCompressedWorldPosition(streamId, paramsRelative); local z2 = z + Utils.readCompressedWorldPosition(streamId, paramsRelative); Utils.updateFruitWindrowArea(fruitType, x, z, x1, z1, x2, z2, 0); end; end; function EasyFlowAreaEvent:writeStream(streamId, connection) local numAreas = table.getn(self.cuttingAreas); streamWriteUIntN(streamId, numAreas, 4); streamWriteUIntN(streamId, self.fruitType, FruitUtil.sendNumBits); local params = g_currentMission.areaCompressionParams; local paramsRelative = g_currentMission.areaRelativeCompressionParams; for i=1, numAreas do local d = self.cuttingAreas; Utils.writeCompressedWorldPosition(streamId, d[1], params); Utils.writeCompressedWorldPosition(streamId, d[2], params); Utils.writeCompressedWorldPosition(streamId, d[3] - d[1], paramsRelative); Utils.writeCompressedWorldPosition(streamId, d[4] - d[2], paramsRelative); Utils.writeCompressedWorldPosition(streamId, d[5] - d[1], paramsRelative); Utils.writeCompressedWorldPosition(streamId, d[6] - d[2], paramsRelative); end end; function EasyFlowAreaEvent:run(connection) print("Error: Do not run EasyFlowAreaEvent locally"); end; function EasyFlowAreaEvent.runLocally(cuttingAreas, fruitType) local numAreas = table.getn(cuttingAreas); local params = g_currentMission.areaCompressionParams; local paramsRelative = g_currentMission.areaRelativeCompressionParams; local volumeSum = 0; local areaSum = 0; for i=1, numAreas do local d = cuttingAreas; local x = Utils.simWriteCompressedWorldPosition(d[1], params); local z = Utils.simWriteCompressedWorldPosition(d[2], params); local x1 = x + Utils.simWriteCompressedWorldPosition(d[3] - d[1], paramsRelative); local z1 = z + Utils.simWriteCompressedWorldPosition(d[4] - d[2], paramsRelative); local x2 = x + Utils.simWriteCompressedWorldPosition(d[5] - d[1], paramsRelative); local z2 = z + Utils.simWriteCompressedWorldPosition(d[6] - d[2], paramsRelative); local area = Utils.updateFruitWindrowArea(fruitType, x, z, x1, z1, x2, z2, 0); if area > 0 then -- now that we removed the windrow, maybe there is some hidden drygrass to grow (set it to growth state 1 if there is some) if fruitType == FruitUtil.FRUITTYPE_GRASS then Utils.switchFruitTypeArea(FruitUtil.FRUITTYPE_GRASS, FruitUtil.FRUITTYPE_DRYGRASS, x, z, x1, z1, x2, z2, 1); end areaSum = areaSum + area; volumeSum = areaSum end end; return volumeSum, areaSum; end; | ![]() |
![]() | ![]() | ![]() |
Anbei die Beiden Lua des EasyFlow
Danke
mfg Meggerpott