-- -- UserWindrower -- Class for all windrowers -- -- @author Stefan Geiger modified by farmer joe -- @date 11/05/08 -- UserWindrower = {}; function UserWindrower.prerequisitesPresent(specializations) return true; end; function UserWindrower:load(xmlFile) self.groundReferenceThreshold = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.groundReferenceNode#threshold"), 0.2); self.groundReferenceNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.groundReferenceNode#index")); if self.groundReferenceNode == nil then self.groundReferenceNode = self.components[1].node; end; self.animation = {}; self.animation.animCharSet = 0; self.animationEnabled = false; local rootNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.animation#rootNode")); if rootNode ~= nil then self.animation.animCharSet = getAnimCharacterSet(rootNode); if self.animation.animCharSet ~= 0 then self.animation.clip = getAnimClipIndex(self.animation.animCharSet, getXMLString(xmlFile, "vehicle.animation#animationClip")); if self.animation.clip >= 0 then assignAnimTrackClip(self.animation.animCharSet, 0, self.animation.clip); self.animation.speedScale = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.animation#speedScale"), 1); setAnimTrackSpeedScale(self.animation.animCharSet, self.animation.clip, self.animation.speedScale); setAnimTrackLoopState(self.animation.animCharSet, 0, true); end; end; end; local numWindrowerDropAreas = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.windrowerDropAreas#count"), 0); if numWindrowerDropAreas ~= 1 or numWindrowerDropAreas ~= table.getn(self.cuttingAreas) then print("Warning: number of cutting areas and drop areas should be equal"); end; self.windrowerDropAreas = {} for i=1, numWindrowerDropAreas do self.windrowerDropAreas[i] = {}; local areanamei = string.format("vehicle.windrowerDropAreas.windrowerDropArea%d", i); self.windrowerDropAreas[i].start = Utils.indexToObject(self.components, getXMLString(xmlFile, areanamei .. "#startIndex")); self.windrowerDropAreas[i].width = Utils.indexToObject(self.components, getXMLString(xmlFile, areanamei .. "#widthIndex")); self.windrowerDropAreas[i].height = Utils.indexToObject(self.components, getXMLString(xmlFile, areanamei .. "#heightIndex")); end; local numCuttingAreas = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.cuttingAreas#count"), 0); for i=1, numCuttingAreas do local areanamei = string.format("vehicle.cuttingAreas.cuttingArea%d", i); self.cuttingAreas[i].foldMinLimit = Utils.getNoNil(getXMLFloat(xmlFile, areanamei .. "#foldMinLimit"), 0); self.cuttingAreas[i].foldMaxLimit = Utils.getNoNil(getXMLFloat(xmlFile, areanamei .. "#foldMaxLimit"), 1); end; local windrowerSound = getXMLString(xmlFile, "vehicle.windrowerSound#file"); if windrowerSound ~= nil and windrowerSound ~= "" then windrowerSound = Utils.getFilename(windrowerSound, self.baseDirectory); self.windrowerSound = createSample("windrowerSound"); self.windrowerSoundEnabled = false; loadSample(self.windrowerSound, windrowerSound, false); self.windrowerSoundPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.windrowerSound#pitchOffset"), 1); self.windrowerSoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.windrowerSound#volume"), 1.0); end; self.isTurnedOn = false; self.wasToFast = false; self.dtDelay = 2; self.dtCount = false; self.currentspeedScale =0; self.dtTime = 0; end; function UserWindrower:delete() if self.windrowerSound ~= nil then delete(self.windrowerSound); end; end; function UserWindrower:mouseEvent(posX, posY, isDown, isUp, button) end; function UserWindrower:keyEvent(unicode, sym, modifier, isDown) end; function UserWindrower:update(dt) self.wasToFast = false; if self:getIsActiveForInput() then if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA) then self.isTurnedOn = not self.isTurnedOn; end; end; if self:getIsActive() then if self.isTurnedOn then local toFast = self:doCheckSpeedLimit() and self.lastSpeed*3600 > 31; if not toFast then local x,y,z = getWorldTranslation(self.groundReferenceNode); local terrainHeight = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, 0, z); if terrainHeight+self.groundReferenceThreshold >= y then local numDropAreas = table.getn(self.windrowerDropAreas); local numAreas = table.getn(self.cuttingAreas); local sum = 0; local fruitType = FruitUtil.FRUITTYPE_GRASS; local fruitTypeFix = false; local foldAnimTime = self.foldAnimTime; for i=1, 3 do if i==2 then fruitType = FruitUtil.FRUITTYPE_WHEAT; elseif i==3 then fruitType = FruitUtil.FRUITTYPE_BARLEY; end; for j=1, numAreas do local cuttingArea = self.cuttingAreas[j]; if foldAnimTime == nil or (foldAnimTime <= cuttingArea.foldMaxLimit and foldAnimTime >= cuttingArea.foldMinLimit) then local x,y,z = getWorldTranslation(cuttingArea.start); local x1,y1,z1 = getWorldTranslation(cuttingArea.width); local x2,y2,z2 = getWorldTranslation(cuttingArea.height); local ratio = g_currentMission.windrowCutLongRatio; if not fruitTypeFix and i==1 then fruitType = FruitUtil.FRUITTYPE_GRASS; end; local area = Utils.updateFruitCutLongArea(fruitType, x, z, x1, z1, x2, z2, 0)/ratio; area = area + Utils.updateFruitWindrowArea(fruitType, x, z, x1, z1, x2, z2, 0); if area == 0 and not fruitTypeFix then fruitType = FruitUtil.FRUITTYPE_DRYGRASS; area = Utils.updateFruitCutLongArea(fruitType, x, z, x1, z1, x2, z2, 0)/ratio; area = area + Utils.updateFruitWindrowArea(fruitType, x, z, x1, z1, x2, z2, 0); end; if area > 0 then fruitTypeFix = true; end; if numDropAreas >= numAreas then if area > 0 then local dropArea = self.windrowerDropAreas[j]; local x,y,z = getWorldTranslation(dropArea.start); local x1,y1,z1 = getWorldTranslation(dropArea.width); local x2,y2,z2 = getWorldTranslation(dropArea.height); local old, total = Utils.getFruitWindrowArea(fruitType, x, z, x1, z1, x2, z2); area = area + old; local value = area / total; if value < 1 and value > 0.08 then value = 1; else value = math.floor(value + 0.6); -- round, biased to the bigger value end; if value >= 1 then value = math.min(value, g_currentMission.maxWindrowValue); Utils.updateFruitWindrowArea(fruitType, x, z, x1, z1, x2, z2, value, true); end; end; else sum = sum + area; end; end; end; if sum > 0 and numDropAreas > 0 then local dropArea = self.windrowerDropAreas[1]; local x,y,z = getWorldTranslation(dropArea.start); local x1,y1,z1 = getWorldTranslation(dropArea.width); local x2,y2,z2 = getWorldTranslation(dropArea.height); local old, total = Utils.getFruitWindrowArea(fruitType, x, z, x1, z1, x2, z2); sum = sum + old; local value = math.floor(sum / total + 0.7); -- round, biased to the bigger value if value >= 1 then value = math.min(value, g_currentMission.maxWindrowValue); Utils.updateFruitWindrowArea(fruitType, x, z, x1, z1, x2, z2, value, true); end; end; end; end; end; if not self.animationEnabled then enableAnimTrack(self.animation.animCharSet, 0); self.animationEnabled = true; self.dtCount = true; end; if not self.windrowerSoundEnabled and self:getIsActiveForSound() then playSample(self.windrowerSound, 0, self.windrowerSoundVolume, 0); setSamplePitch(self.windrowerSound, self.windrowerSoundPitchOffset); self.windrowerSoundEnabled = true; end; self.wasToFast = toFast; else if self.animationEnabled then self.animationEnabled = false; self.dtCount = true; end; end; if self.dtCount then if self.animationEnabled then self.dtTime = self.dtTime+dt/1000; if self.dtTime <= 1 and self.dtTime >=0 then setAnimTrackSpeedScale(self.animation.animCharSet, self.animation.clip, self.animation.speedScale * self.dtTime); else self.dtTime = 1; self.dtCount = false; end; else self.dtTime = self.dtTime-dt/3000; if self.dtTime <= 1 and self.dtTime >=0 then setAnimTrackSpeedScale(self.animation.animCharSet, self.animation.clip, self.animation.speedScale * self.dtTime); else self.dtTime = 0; disableAnimTrack(self.animation.animCharSet, 0); self.dtCount = false; end; end; end; end; if not self.isTurnedOn and self.windrowerSoundEnabled then stopSample(self.windrowerSound); self.windrowerSoundEnabled = false; end; end; function UserWindrower:draw() if self.isTurnedOn then g_currentMission:addHelpButtonText(string.format(g_i18n:getText("turn_off_OBJECT"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA); else g_currentMission:addHelpButtonText(string.format(g_i18n:getText("turn_on_OBJECT"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA); end; if self.wasToFast then g_currentMission:addWarning(g_i18n:getText("Dont_drive_to_fast") .. "\n" .. string.format(g_i18n:getText("Cruise_control_levelN"), "2", InputBinding.getButtonKeyName(InputBinding.SPEED_LEVEL2)), 0.07+0.022, 0.019+0.029); end; end; function UserWindrower:onDetach() if self.deactivateOnDetach then UserWindrower.onDeactivate(self); end; end; function UserWindrower:onLeave() if self.deactivateOnLeave then UserWindrower.onDeactivate(self); end; end; function UserWindrower:onDeactivate() if self.animationEnabled then disableAnimTrack(self.animation.animCharSet, 0); self.animationEnabled = false; end; self.isTurnedOn = false; end;