-- -- BGASilo -- -- # Author: Heady -- # date: 06.01.2011 -- # update LS15: 09.11.2014 -- # last update: 25.01.2016 -- -- > Not for commercial use < -- -- > Not allowed for edit - Copyright (C) Heady - www.planet-ls.de < -- -- print(" BGA Silo v15.0.0 by Heady loaded"); ModEvent = {}; ModEvent.silos = {}; function ModEvent:loadMap(name) if g_server ~= nil then self.savegameDir = getUserProfileAppPath() .. "savegame"..g_currentMission.missionInfo.savegameIndex; createFolder(self.savegameDir); --self.saveXMLFile = self.savegameDir .. "/bgaSilo.xml"; self.saveXMLFile = "bgaSilo.xml"; self.fileFound = false; getFiles(self.savegameDir, "getFilesCallback", self); if g_currentMission.missionStats.fuelUsageTotal == 0 then --print("g_currentMission.missionStats.fuelUsageTotal 0") --os.remove(self.saveXMLFile); local xml = createXMLFile("createsilo", self.savegameDir.."/"..self.saveXMLFile, "bgaSilos"); delete(xml); else ModEvent:loadBGASiloFromFile(); end; end; end; function ModEvent:getFilesCallback(filename) if filename == self.saveXMLFile then self.fileFound = true; end; end; function ModEvent:deleteMap() ModEvent.silos = {}; end; function ModEvent:delete() end; function ModEvent:mouseEvent(posX, posY, isDown, isUp, button) end; function ModEvent:keyEvent(unicode, sym, modifier, isDown) end; function ModEvent:update(dt) end; function ModEvent:draw() for i=1, table.getn(ModEvent.silos) do ModEvent.silos[i]:draw(); end; end; local CareerScreenSaveSelectedGame = CareerScreen.saveSavegame; CareerScreen.saveSavegame = function(self, savegame) CareerScreenSaveSelectedGame(self, savegame); ModEvent:saveBGASiloToXML(); print("MapBGASilo run CareerScreen.saveSavegame"); end; function ModEvent:saveBGASiloToXML() print("MapBGASilo run saveBGASiloToXML()"); local xml = createXMLFile("createsilo", self.savegameDir.."/"..self.saveXMLFile, "bgaSilos"); for i,silo in pairs(ModEvent.silos) do print("MapBGASilo do xml saveXMLFile entry"); setXMLInt(xml, string.format("bgaSilos.silo%d#silageFillLevel", i), silo.silage.fillLevel); setXMLInt(xml, string.format("bgaSilos.silo%d#siloFillLevel", i), silo.silo.fillLevel); setXMLInt(xml, string.format("bgaSilos.silo%d#siloMaxFillLevel", i), silo.silo.maxFillLevel); setXMLInt(xml, string.format("bgaSilos.silo%d#compFillLevel", i), silo.compFillLevel); setXMLInt(xml, string.format("bgaSilos.silo%d#state", i), silo.siloState); --print("silo.compScale ", silo.compScale) setXMLString(xml, string.format("bgaSilos.silo%d#compScale", i), string.format("%f", silo.compScale)); end; saveXMLFile(xml); delete(xml); end; function ModEvent:loadBGASiloFromFile() --[[local existFile = false; local files = Files:new(self.savegameDir); for k,v in pairs(files.files) do --print("filename: ", v.filename, " isDirectory: ", v.isDirectory); if self.saveXMLFile == v.filename then existFile = true; break; end; end;]] --local existDir = io.open (self.saveXMLFile, "r"); if self.fileFound then local xmlFile = loadXMLFile("bgaSilos", self.savegameDir.."/"..self.saveXMLFile); local siloI = 1; while true do local key = string.format("bgaSilos.silo%d", siloI); local siloMaxFillLevel = getXMLFloat(xmlFile, key.."#siloMaxFillLevel"); if siloMaxFillLevel ~= nil then if ModEvent.silos[siloI] ~= nil then ModEvent.silos[siloI].silage.fillLevel = getXMLInt(xmlFile, key.."#silageFillLevel"); ModEvent.silos[siloI].silo.fillLevel = getXMLInt(xmlFile, key.."#siloFillLevel"); ModEvent.silos[siloI].silo.maxFillLevel = siloMaxFillLevel; ModEvent.silos[siloI].compFillLevel = getXMLInt(xmlFile, key.."#compFillLevel"); ModEvent.silos[siloI].siloState = getXMLInt(xmlFile, key.."#state"); ModEvent.silos[siloI].compScale = getXMLFloat(xmlFile, key.."#compScale"); ModEvent.silos[siloI]:updateState(ModEvent.silos[siloI].siloState); ModEvent.silos[siloI]:moveSilagePlane(ModEvent.silos[siloI].silage.fillLevel); ModEvent.silos[siloI]:moveSiloPlane(ModEvent.silos[siloI].silo.fillLevel); end; else print("MapBGASilo: BGASilo saves loaded"); break; end; siloI = siloI +1; end; delete(xmlFile); --print("BGASilo saves loaded"); else print("MapBGASilo: ", self.saveXMLFile, " can not be found, BGASilo saves not loaded.") end; end; function ModEvent:modMapBGASiloCompareScale(scale) if scale == nil then if table.getn(ModEvent.silos) >= 1 then return ">modMapBGASiloCompareScale "..tostring(ModEvent.silos[1].compScale); else return ">Kein BGASilo auf der Map"; end; else --print("scale: ", tostring(scale)); -- todo scale auf number überprüfen --> string --> print("zahl eingeben"); for i=1, table.getn(ModEvent.silos) do ModEvent.silos[i].compScale = tonumber(string.format("%f", scale)); ModEvent.silos[i].doUpdateSendEvent = true; end; return ">modMapBGASiloCompareScale "..tostring(scale); end; end; addConsoleCommand("modMapBGASiloCompareScale", "Changes the compare scale by BGA Silo v2", "modMapBGASiloCompareScale", ModEvent); function ModEvent:modMapBGASiloPrintDebug(arg) if arg == nil then return ">use argument: 'self' or 'server'"; end; if arg == "server" then for i=1, table.getn(ModEvent.silos) do ModEvent.silos[i]:updateSendEventPrintDebug(); end; else print("------------------------------------------------------------") for i=1, table.getn(ModEvent.silos) do local silo = ModEvent.silos[i]; print("silo["..i.."].silage.fillLevel: ", silo.silage.fillLevel); print("silo["..i.."].silo.fillLevel: ", silo.silo.fillLevel); print("silo["..i.."].silo.maxFillLevel: ", silo.silo.maxFillLevel); print("silo["..i.."].siloState: ", silo.siloState); print("silo["..i.."].siloIsFull: ", silo.siloIsFull); print("silo["..i.."].compFillLevel: ", silo.compFillLevel); print("silo["..i.."].compScale: ", silo.compScale); print("------------------------------------------------------------") end; print("------------------------------------------------------------") end; end; addConsoleCommand("modMapBGASiloPrintDebug", "print Debug BGA Silo v2", "modMapBGASiloPrintDebug", ModEvent); addModEventListener(ModEvent); function onCreate(self, id) --print("created MapBGASilo, id: ", id); local instance = MapBGASilo:new(g_server ~= nil, g_client ~= nil); local index = g_currentMission:addOnCreateLoadedObject(instance); instance:load(id); instance:register(true); -- add update routine, table.insert(ModEvent.silos, instance); end; MapBGASilo = {}; local MapBGASilo_mt = Class(MapBGASilo, Object); function MapBGASilo:new(isServer, isClient) local self = Object:new(isServer, isClient, MapBGASilo_mt); self.className = "MapBGASilo"; return self; end; function MapBGASilo:load(id) --local triggerId = Utils.indexToObject(nodeId, getUserAttribute(nodeId, "triggerIndex")); --self.triggerId = triggerId; --addTrigger(self.triggerId, "triggerCallback", self); self.isHeadyBGASilo = true; self.allowFillTypes = {}; local types = Utils.splitString(" ", getUserAttribute(id, "fillTypes")); for k,v in pairs(types) do --if FruitUtil.fruitTypes[v] ~= nil then --self.allowFillTypes[FruitUtil.fruitTypeToFillType[FruitUtil.fruitTypes[v].index]] = true; --end; if Fillable.fillTypeNameToDesc[v] ~= nil then self.allowFillTypes[Fillable.fillTypeNameToDesc[v].index] = true; end; end; local capacityStr = getUserAttribute(id, "capacity"); self.capacity = Utils.getNoNil(tonumber(capacityStr), 100000); --self.fillLevel = 0; self.tipTriggerNode = Utils.indexToObject(id, getUserAttribute(id, "tipTriggerIndex")); addTrigger(self.tipTriggerNode, "TipTriggerCallback", self); self.triggerId = self.tipTriggerNode; self.addTipTrigger = false; self.removeTipTrigger = false; g_currentMission:addTipTrigger(self); self.triggerStartId = self.triggerId; self.triggerTipWidth = math.huge; self.isAreaTrigger = Utils.getNoNil(getNumOfChildren(self.tipTriggerNode) > 0, false); if self.isAreaTrigger then self.triggerStartId = getChildAt(self.tipTriggerNode, 0); self.triggerEndId = getChildAt(self.tipTriggerNode, 1); self.triggerWidth = Utils.getNoNil(getUserAttribute(self.tipTriggerNode, "triggerWidth"), 5); end; self.priceMultipliers = {}; -- cheat standard script for i=1, Fillable.NUM_FILLTYPES do self.priceMultipliers[i] = 0; end; self.silageAttrNode = Utils.indexToObject(id, getUserAttribute(id, "silageAttrIndex")); self.silage = {}; if self.silageAttrNode ~= nil then self.silage.mainNode = Utils.indexToObject(self.silageAttrNode, getUserAttribute(self.silageAttrNode, "silageIndex")); -- todo setzte tg in den untergrund: y = -100 ??? setVisibility(self.silage.mainNode, false); setTranslation(self.silage.mainNode, 0,-100,0); self.silage.planeNode = Utils.indexToObject(self.silageAttrNode, getUserAttribute(self.silageAttrNode, "silagePlaneIndex")); self.silage.colsNode = Utils.indexToObject(self.silageAttrNode, getUserAttribute(self.silageAttrNode, "colsIndex")); self.silage.colsNumChilds = getNumOfChildren(self.silage.colsNode); for i=1, self.silage.colsNumChilds do local childNode = getChildAt(self.silage.colsNode, i-1); g_currentMission:addNodeObject(childNode, self); -- raycast callback; shovel, etc. end; --g_currentMission:addNodeObject(self.silage.colNode, self); -- raycast callback; shovel, etc. self.nodeObjectPrio = 100; local minY, maxY = Utils.getVectorFromString(getUserAttribute(self.silageAttrNode, "moveMinMaxY")); if minY ~= nil and maxY ~= nil then self.silage.moveMinY = minY; self.silage.moveMaxY = maxY; self.silage.movingNode = Utils.indexToObject(self.silageAttrNode, getUserAttribute(self.silageAttrNode, "movingIndexY")); end; local silageClipName = getUserAttribute(self.silageAttrNode, "silageAnimClipName"); if silageClipName ~= nil then self.silage.animNode = Utils.indexToObject(self.silageAttrNode, getUserAttribute(self.silageAttrNode, "silageAnimIndex")); local animCharSet = getAnimCharacterSet(self.silage.animNode); if animCharSet ~= 0 then local clip = getAnimClipIndex(animCharSet, silageClipName); if clip >= 0 then self.silage.animCharSet = animCharSet; assignAnimTrackClip(self.silage.animCharSet, 0, clip); setAnimTrackLoopState(self.silage.animCharSet, 0, false); self.silage.animDuration = getAnimClipDuration(self.silage.animCharSet, clip); else print("Warning: MapBGASilo ["..getName(self.silageAttrNode).." | id: "..self.silageAttrNode.."] UserAttribute /silageAnimClipName/ is set, but Clip not found!"); end; else print("Warning: MapBGASilo ["..getName(self.silageAttrNode).." | id: "..self.silageAttrNode.."] UserAttribute /silageAnimClipName/ is set, but AnimationSet at node in /silageAnimIndex/ not found!"); end; end; self.maxSiloState = 1; self.folie = {}; self.folie.planeNode = Utils.indexToObject(self.silageAttrNode, getUserAttribute(self.silageAttrNode, "foliePlaneIndex")); setVisibility(self.folie.planeNode, false); end; self.silage.fillLevel = 0; self.silage.maxFillLevel = self.capacity; self.siloAttrNode = Utils.indexToObject(id, getUserAttribute(id, "siloAttrIndex")); self.silo = {}; if self.siloAttrNode ~= nil then self.silo.mainNode = Utils.indexToObject(self.siloAttrNode, getUserAttribute(self.siloAttrNode, "siloIndex")); setVisibility(self.silo.mainNode, false); setTranslation(self.silo.mainNode, 0,-100,0); self.silo.triggersRefNode = Utils.indexToObject(self.siloAttrNode, getUserAttribute(self.siloAttrNode, "siloTriggersRefIndex")); self.silo.positionTriggersNode = Utils.indexToObject(self.siloAttrNode, getUserAttribute(self.siloAttrNode, "siloPositionTriggersIndex")); self.silo.triggersNode = Utils.indexToObject(self.siloAttrNode, getUserAttribute(self.siloAttrNode, "siloTriggersIndex")); self.silo.triggersNumChilds = getNumOfChildren(self.silo.triggersNode); for i=1, self.silo.triggersNumChilds do local childNode = getChildAt(self.silo.triggersNode, i-1); addTrigger(childNode, "shovelGetCallback", self); end; local minZ, maxZ = Utils.getVectorFromString(getUserAttribute(self.siloAttrNode, "scaleMinMaxZ")); if minZ ~= nil and maxZ ~= nil then self.silo.moveMinZ = minZ; self.silo.moveMaxZ = maxZ; self.silo.movingNode = Utils.indexToObject(self.siloAttrNode, getUserAttribute(self.siloAttrNode, "movingIndexZ")); end; local siloClipName = getUserAttribute(self.siloAttrNode, "siloAnimClipName"); if siloClipName ~= nil then self.silo.animNode = Utils.indexToObject(self.siloAttrNode, getUserAttribute(self.siloAttrNode, "siloAnimIndex")); self.silo.animInvert = Utils.getNoNil(getUserAttribute(self.siloAttrNode, "siloAnimInvert"), false); local animCharSet = getAnimCharacterSet(self.silo.animNode); if animCharSet ~= 0 then local clip = getAnimClipIndex(animCharSet, siloClipName); if clip >= 0 then self.silo.animCharSet = animCharSet; assignAnimTrackClip(self.silo.animCharSet, 0, clip); setAnimTrackLoopState(self.silo.animCharSet, 0, false); self.silo.animDuration = getAnimClipDuration(self.silo.animCharSet, clip); else print("Warning: MapBGASilo ["..getName(self.siloAttrNode).." | id: "..self.siloAttrNode.."] UserAttribute /siloAnimClipName/ is set, but Clip not found!"); end; else print("Warning: MapBGASilo ["..getName(self.siloAttrNode).." | id: "..self.siloAttrNode.."] UserAttribute /siloAnimClipName/ is set, but AnimationSet at node in /siloAnimIndex/ not found!"); end; end; self.maxSiloState = 2; end; self.silo.outputFillType = Fillable.FILLTYPE_SILAGE; self.silo.fillLevel = 0; self.silo.maxFillLevel = self.silage.maxFillLevel self.currentShovel = nil; self.currentShovelNode = nil; self.playerInRange = false; self.siloState = 0; if self.maxSiloState == nil then self.maxSiloState = 0; end; self.siloState2 = false; self.siloIsFull = false; self.changeFillLevelState2 = false; self.printStrg = false; self.setTipTrigger = true; self.isTipTrigger = true; self.trailersInTrigger = {}; -- variables for moving down self.vehicleInTrigger = {}; self.compFillLevel = 0; self.compScale = 3; self.doUpdateSendEvent = false; self.doUpdateMoveSilagePlane = false; self.doUpdateMoveSiloPlane = false; self.doUpdateCompFillLevel = false; self.mpDirtyFlag = self:getNextDirtyFlag(); self:updateState(self.siloState); self:moveSilagePlane(self.silage.fillLevel); self:moveSiloPlane(self.silo.fillLevel); end; function MapBGASilo:delete() removeTrigger(self.tipTriggerNode); for i=1, self.silo.triggersNumChilds do local childNode = getChildAt(self.silo.triggersNode, i-1); removeTrigger(childNode); end; for i=1, self.silage.colsNumChilds do local childNode = getChildAt(self.silage.colsNode, i-1); g_currentMission:removeNodeObject(childNode); end; g_currentMission:removeTipTrigger(self); for k,v in pairs(g_currentMission.trailerTipTriggers) do for key, tipTrigger in pairs(v) do if tipTrigger == self then v[key] = nil; end; end; end; end; function MapBGASilo:mouseEvent(posX, posY, isDown, isUp, button) end; function MapBGASilo:keyEvent(unicode, sym, modifier, isDown) end; function MapBGASilo:readStream(streamId, connection) if connection:getIsServer() then self.siloState = streamReadInt32(streamId); self.silage.fillLevel = streamReadInt32(streamId); self.silo.fillLevel = streamReadInt32(streamId); self.silo.maxFillLevel = streamReadInt32(streamId); self.compFillLevel = streamReadInt32(streamId); self.compScale = streamReadInt32(streamId); self.setTipTrigger = streamReadBool(streamId); self.isTipTrigger = streamReadBool(streamId); self:updateState(self.siloState); self:moveSilagePlane(self.silage.fillLevel); self:moveSiloPlane(self.silo.fillLevel); end end; function MapBGASilo:writeStream(streamId, connection) if not connection:getIsServer() then streamWriteInt32(streamId, self.siloState); streamWriteInt32(streamId, self.silage.fillLevel); streamWriteInt32(streamId, self.silo.fillLevel); streamWriteInt32(streamId, self.silo.maxFillLevel); streamWriteInt32(streamId, self.compFillLevel); streamWriteInt32(streamId, self.compScale); streamWriteBool(streamId, self.setTipTrigger); streamWriteBool(streamId, self.isTipTrigger); end; end; function MapBGASilo:readUpdateStream(streamId, timestamp, connection) if connection:getIsServer() then self.silage.fillLevel = streamReadInt32(streamId); self.silo.fillLevel = streamReadInt32(streamId); self.silo.maxFillLevel = streamReadInt32(streamId); self.compFillLevel = streamReadInt32(streamId); self:moveSilagePlane(self.silage.fillLevel); self:moveSiloPlane(self.silo.fillLevel); end; end; function MapBGASilo:writeUpdateStream(streamId, connection, dirtyMask) if not connection:getIsServer() then streamWriteInt32(streamId, self.silage.fillLevel); streamWriteInt32(streamId, self.silo.fillLevel); streamWriteInt32(streamId, self.silo.maxFillLevel); streamWriteInt32(streamId, self.compFillLevel); end; end; function MapBGASilo:update(dt) self.printStrg = false; if self:getPlayerShowInfo() then if InputBinding.hasEvent(InputBinding.BGASILO_STATE) and self.silage.fillLevel > 0 and self.silo.outputFillType ~= Fillable.FILLTYPE_MANURE and table.getn(self.vehicleInTrigger) < 1 then self.siloState = self.siloState +1; if self.siloState >= self.maxSiloState +1 then self.siloState = 0; end; --if g_server ~= nil then self:updateState(self.siloState); --end; self.doUpdateSendEvent = true; end; if InputBinding.hasEvent(InputBinding.BGASILO_TIPTRIGGER) then if self.isTipTrigger then self.setTipTrigger = false; else if table.getn(self.trailersInTrigger) < 1 then self.setTipTrigger = true; end; end; self.doUpdateSendEvent = true; end; if Input.isKeyPressed(Input.KEY_lctrl) then self.printStrg = true; end; end; if g_server ~= nil then if self.siloState == 1 then self.changeFillLevelState2 = true; end; if self.siloState == 2 and self.changeFillLevelState2 then self.silo.maxFillLevel = self.silage.fillLevel; self.silo.fillLevel = self.silage.fillLevel; self:moveSiloPlane(self.silo.fillLevel); self.changeFillLevelState2 = false; end; if self.siloState == 2 and self.silo.fillLevel <= 0 then self.siloState = 0; self.silage.fillLevel = 0; self.silo.fillLevel = 0; self.compFillLevel = 0; self.silo.outputFillType = Fillable.FILLTYPE_SILAGE; self:moveSilagePlane(self.silage.fillLevel); self:moveSiloPlane(self.silo.fillLevel); self:updateState(self.siloState); self.doUpdateSendEvent = true; end; if self.siloState == 2 then if self.silo.fillLevel < self.silage.fillLevel - self.compFillLevel then self.silo.outputFillType = Fillable.FILLTYPE_MANURE; end; self.siloState2 = true; end; if self.siloState == 0 and self.silo.fillLevel > 0 and self.siloState2 then local n = self.compFillLevel / self.silage.fillLevel; self.silage.fillLevel = self.silo.fillLevel; self.compFillLevel = self.silage.fillLevel * n; self.siloState2 = false; end; end; if self.siloState == 0 and self.silage.fillLevel >= self.silage.maxFillLevel then self.siloIsFull = true; else self.siloIsFull = false; end; if table.getn(self.trailersInTrigger) < 1 then if not self.isTipTrigger and self.setTipTrigger then g_currentMission:addTipTrigger(self); self.isTipTrigger = true; end; end; if self.isTipTrigger and not self.setTipTrigger then g_currentMission:removeTipTrigger(self); for keyTrailer, ttable in pairs(g_currentMission.trailerTipTriggers) do for k, tipTrigger in pairs(ttable) do if tipTrigger == self then g_currentMission.trailerTipTriggers[keyTrailer][k] = nil; end; end; end; self.isTipTrigger = false; end; self:drawUpdate(); -- LS13 extraPrintText in draw do not work - store at update routine end; function MapBGASilo:updateTick(dt) if g_server ~= nil then if self.currentShovel ~= nil and self.silo.fillLevel > 0 and self.siloState == 2 then -- get the shovel object again (maybe it was deleted in the meantime) local shovel = g_currentMission.nodeToVehicle[self.currentShovelNode]; self.currentShovel = shovel; if shovel ~= nil then if shovel.fillLevel < shovel.capacity and shovel:getAllowFillShovel(self.silo.outputFillType) then local deltaFillLevel = shovel:fillShovelFromTrigger(self, self.silo.fillLevel, self.silo.outputFillType, dt); self.silo.fillLevel = self.silo.fillLevel - deltaFillLevel; self:moveSiloPlane(self.silo.fillLevel); end; local attacherRootVehicle = shovel:getRootAttacherVehicle(); local gesMass = 0; for c=1, table.getn(attacherRootVehicle.components) do gesMass = gesMass + getMass(attacherRootVehicle.components[c].node); end; for i=1, table.getn(attacherRootVehicle.attachedImplements) do local implement = attacherRootVehicle.attachedImplements[i].object; for ci=1, table.getn(implement.components) do gesMass = gesMass + getMass(implement.components[ci].node); end; end; --local fres = attacherRootVehicle.lastMovedDistance*30*gesMass*dt; --if attacherRootVehicle.movingDirection == 1 then --local worldX,worldY,worldZ = localDirectionToWorld(attacherRootVehicle.components[1].node, 0, 0, -fres); --addForce(attacherRootVehicle.components[1].node, worldX, worldY, worldZ, attacherRootVehicle.components[1].centerOfMass[1], attacherRootVehicle.components[1].centerOfMass[2], attacherRootVehicle.components[1].centerOfMass[3], true); --end; local vx, vy, vz = worldDirectionToLocal(attacherRootVehicle.components[1].node, getLinearVelocity(attacherRootVehicle.components[1].node)); local attacherRootVehicleLastSpeed = Utils.vector3Length(vx, vy, vz); local pres = (attacherRootVehicleLastSpeed*gesMass)*0.5; if shovel.silageSchild ~= nil and shovel.silageSchild.htpForceScale ~= nil then pres = (attacherRootVehicleLastSpeed*gesMass)*shovel.silageSchild.htpForceScale; end; if attacherRootVehicle.movingDirection == 1 and pres > 0 then --if attacherRootVehicle.isForcedByHTP == nil or attacherRootVehicle.isForcedByHTP == self then --attacherRootVehicle.isForcedByHTP = self; --self.lastVehicleForced = attacherRootVehicle; local worldX,worldY,worldZ = localDirectionToWorld(attacherRootVehicle.components[1].node, 0, 0, -pres); --addForce(attacherRootVehicle.components[1].node, worldX, worldY, worldZ, attacherRootVehicle.components[1].centerOfMass[1], attacherRootVehicle.components[1].centerOfMass[2], attacherRootVehicle.components[1].centerOfMass[3], true); addImpulse(attacherRootVehicle.components[1].node, worldX, worldY, worldZ, attacherRootVehicle.components[1].centerOfMass[1], attacherRootVehicle.components[1].centerOfMass[2], attacherRootVehicle.components[1].centerOfMass[3], true); --end; end; end; end; if self.doUpdateMoveSilagePlane or self.doUpdateMoveSiloPlane or self.doUpdateCompFillLevel then self:raiseDirtyFlags(self.mpDirtyFlag); self.doUpdateMoveSilagePlane = false; self.doUpdateMoveSiloPlane = false; self.doUpdateCompFillLevel = false; end; if self.siloState == 0 and self.silage.fillLevel > 0 then self:updateDriveDown(dt); end; end; if self.doUpdateSendEvent then self:updateSendEvent(); self.doUpdateSendEvent = false; end; end; function MapBGASilo:updateTrailerTipping(trailer, fillDelta, fillType) self.silage.fillLevel = self.silage.fillLevel - fillDelta; self:moveSilagePlane(self.silage.fillLevel); end; function MapBGASilo:getTipInfoForTrailer(trailer, tipReferencePointIndex) local minDistance, bestPoint = TipTrigger.getTipDistanceFromTrailer(self, trailer, tipReferencePointIndex); local isAllowed = false; if self.allowFillTypes[trailer.currentFillType] and not self.siloIsFull then isAllowed = true; end; return isAllowed, minDistance, bestPoint; end; function MapBGASilo:getNoAllowedText(trailer) if trailer.currentFillType ~= Fillable.FILLTYPE_UNKNOWN and not self.allowFillTypes[trailer.currentFillType] then return Fillable.fillTypeIndexToDesc[trailer.currentFillType].nameI18N .. g_i18n:getText("notAcceptedHere"); end; return nil; end; function MapBGASilo:getAllowShovelFillType(fillType) local allowed = false; if self.allowFillTypes[fillType] then allowed = true; end; return allowed; end; function MapBGASilo:addShovelFillLevel(shovel, delta, currentFillType) if not self.siloIsFull then self.silage.fillLevel = self.silage.fillLevel + delta; self:moveSilagePlane(self.silage.fillLevel); return delta; end; return 0; end; function MapBGASilo:moveSilagePlane(fillLevel) if g_server ~= nil then self.doUpdateMoveSilagePlane = true; end; if self.silage.moveMinY ~= nil and self.silage.moveMaxY ~= nil and self.silage.movingNode then local m = (self.silage.moveMaxY - self.silage.moveMinY) / self.silage.maxFillLevel; local xPos, yPos, zPos = getTranslation(self.silage.movingNode); setTranslation(self.silage.movingNode, xPos, m*fillLevel + self.silage.moveMinY, zPos); end; if self.silage.animCharSet ~= nil then if self.silage.animCharSet ~= 0 then enableAnimTrack(self.silage.animCharSet, 0); setAnimTrackTime(self.silage.animCharSet, 0, (fillLevel/self.silage.maxFillLevel)*self.silage.animDuration, true); disableAnimTrack(self.silage.animCharSet, 0); end; end; end; function MapBGASilo:moveSiloPlane(fillLevel) if g_server ~= nil then self.doUpdateMoveSiloPlane = true; end; if self.silo.moveMinZ ~= nil and self.silo.moveMaxZ ~= nil and self.silo.movingNode ~= nil then --local n = 2^(1-(fillLevel/self.silo.maxFillLevel)); local n = 1; local m = (self.silo.moveMaxZ - self.silo.moveMinZ) / self.silo.maxFillLevel; local xScale, yScale, zScale = getScale(self.silo.movingNode); setScale(self.silo.movingNode, xScale, yScale, (m*fillLevel*n) + self.silo.moveMinZ); end; if self.silo.triggersRefNode ~= nil and self.silo.positionTriggersNode ~= nil then local xw,yw,zw = getWorldTranslation(self.silo.triggersRefNode); local xl,yl,zl = worldToLocal(getParent(self.silo.positionTriggersNode), xw, yw, zw); setTranslation(self.silo.positionTriggersNode, xl, yl, zl); end; if self.silo.animCharSet ~= nil then if self.silo.animCharSet ~= 0 then if self.silo.animInvert ~= nil then if self.silo.animInvert then enableAnimTrack(self.silo.animCharSet, 0); setAnimTrackTime(self.silo.animCharSet, 0, (1-(fillLevel/self.silo.maxFillLevel))*self.silo.animDuration, true); disableAnimTrack(self.silo.animCharSet, 0); else enableAnimTrack(self.silo.animCharSet, 0); setAnimTrackTime(self.silo.animCharSet, 0, (fillLevel/self.silo.maxFillLevel)*self.silo.animDuration, true); disableAnimTrack(self.silo.animCharSet, 0); end; end; end; end; end; function MapBGASilo:updateState(state) if state == 0 then -- silage setVisibility(self.silo.mainNode, false); setTranslation(self.silo.mainNode, 0,-100,0); setVisibility(self.silage.mainNode, true); setTranslation(self.silage.mainNode, 0,0,0); setVisibility(self.silage.planeNode, true); setVisibility(self.folie.planeNode, false); end; if state == 1 then -- folie setVisibility(self.silo.mainNode, false); setTranslation(self.silo.mainNode, 0,-100,0); setVisibility(self.silage.mainNode, true); setTranslation(self.silage.mainNode, 0,0,0); setVisibility(self.silage.planeNode, false); setVisibility(self.folie.planeNode, true); end; if state == 2 then -- silo setVisibility(self.silo.mainNode, true); setTranslation(self.silo.mainNode, 0,0,0); setVisibility(self.silage.mainNode, false); setTranslation(self.silage.mainNode, 0,-100,0); setVisibility(self.silage.planeNode, false); setVisibility(self.folie.planeNode, false); --self.silo.maxFillLevel = self.silage.fillLevel; --self.silo.fillLevel = self.silage.fillLevel; --self:moveSiloPlane(self.silo.fillLevel); end; end; function MapBGASilo:draw() end; function MapBGASilo:drawUpdate() local printSilageFillLevel = false; local printVerdichtung = false; local printSiloFillLevel = false; if self:getPlayerShowInfo() then if self.printStrg then if self.isTipTrigger then g_currentMission:addExtraPrintText(g_i18n:getText("BGASILO_TIPTRIGGER_1")); else g_currentMission:addExtraPrintText(g_i18n:getText("BGASILO_TIPTRIGGER_2")); if table.getn(self.trailersInTrigger) > 0 then g_currentMission:addWarning(g_i18n:getText("BGASILO_TIPTRIGGER_3")) end; end; end; g_currentMission:addHelpButtonText(g_i18n:getText("BGASILO_TIPTRIGGER"), InputBinding.BGASILO_TIPTRIGGER); if self.siloState == 0 and self.silage.fillLevel > 0 then if table.getn(self.vehicleInTrigger) < 1 then g_currentMission:addHelpButtonText(g_i18n:getText("BGASILO_1"), InputBinding.BGASILO_STATE); else g_currentMission:addWarning(g_i18n:getText("BGASILO_STATE_1")) end; printSilageFillLevel = true; printVerdichtung = true; elseif self.siloState == 1 then if table.getn(self.vehicleInTrigger) < 1 then g_currentMission:addHelpButtonText(g_i18n:getText("BGASILO_2"), InputBinding.BGASILO_STATE); else g_currentMission:addWarning(g_i18n:getText("BGASILO_STATE_1")) end; printSilageFillLevel = true; printVerdichtung = true; elseif self.siloState == 2 then if self.silo.outputFillType == Fillable.FILLTYPE_MANURE then --g_currentMission:addWarning("Der Rest ist vergammelt (Mist) weil nicht verdichtet wurde!".."\n".."Das Silo muss erst leer gefahren, bevor wieder Silage eingefuellt werden kann!".."\n".."Mist FillLevel: "..math.floor(self.silo.fillLevel), 0.05, 0.025+0.007); g_currentMission:addWarning(g_i18n:getText("BGASILO_4").." "..math.floor(self.silo.fillLevel)); else if table.getn(self.vehicleInTrigger) < 1 then g_currentMission:addHelpButtonText(g_i18n:getText("BGASILO_3"), InputBinding.BGASILO_STATE); else g_currentMission:addWarning(g_i18n:getText("BGASILO_STATE_1")) end; printSiloFillLevel = true; end; end; end; if self:getVehicleShowInfo() then if self.siloState == 0 then printSilageFillLevel = true; printVerdichtung = true; elseif self.siloState == 2 then printSiloFillLevel = true; end; end; if printSilageFillLevel then g_currentMission:addExtraPrintText(g_i18n:getText("fill_level")..": "..math.floor(self.silage.fillLevel).." / "..math.floor(self.silage.maxFillLevel).." "..math.floor(self.silage.fillLevel*100/self.silage.maxFillLevel).."%"); end; if printSiloFillLevel then if self.silo.outputFillType == Fillable.FILLTYPE_MANURE then g_currentMission:addExtraPrintText(g_i18n:getText("filltype_manure").." "..g_i18n:getText("fill_level")..": "..math.floor(self.silo.fillLevel).." / "..math.floor(self.silage.fillLevel - self.compFillLevel).." "..math.floor(self.silo.fillLevel*100/(self.silage.fillLevel - self.compFillLevel)).."%"); else g_currentMission:addExtraPrintText(g_i18n:getText("fill_level")..": "..math.floor(self.silo.fillLevel - (self.silage.fillLevel - self.compFillLevel)).." / "..math.floor(self.silage.maxFillLevel).." "..math.floor((self.silo.fillLevel - (self.silage.fillLevel - self.compFillLevel))*100/self.silage.maxFillLevel).."%"); end; end; if printVerdichtung then local fillLevel = self.silage.fillLevel; if fillLevel == 0 then fillLevel = 0.000001; end; g_currentMission:addExtraPrintText(g_i18n:getText("BGASILO_5")..": "..math.floor(self.compFillLevel *100 / fillLevel).."%"); end; end; function MapBGASilo:TipTriggerCallback(triggerId, otherId, onEnter, onLeave, onStay, otherShapeId) if onEnter and self.siloState == 0 then if self.isTipTrigger then local trailer = g_currentMission.objectToTrailer[otherShapeId]; if trailer ~= nil and trailer.allowTipDischarge then if g_currentMission.trailerTipTriggers[trailer] == nil then g_currentMission.trailerTipTriggers[trailer] = {}; end; table.insert(g_currentMission.trailerTipTriggers[trailer], self); table.insert(self.trailersInTrigger, trailer); end; end; elseif onLeave then local trailer = g_currentMission.objectToTrailer[otherShapeId]; if trailer ~= nil and trailer.allowTipDischarge then local triggers = g_currentMission.trailerTipTriggers[trailer]; if triggers ~= nil then for i=1, table.getn(triggers) do if triggers[i] == self then table.remove(triggers, i); if table.getn(triggers) == 0 then g_currentMission.trailerTipTriggers[trailer] = nil; end; break; end; end; end; for i=1, table.getn(self.trailersInTrigger) do if self.trailersInTrigger[i] == trailer then table.remove(self.trailersInTrigger, i); end; end; end; end; if onEnter then if g_currentMission.player ~= nil then if otherId == g_currentMission.player.rootNode then self.playerInRange = true; end; end; elseif onLeave then if g_currentMission.player ~= nil then if otherId == g_currentMission.player.rootNode then self.playerInRange = false; end; end; end; if onEnter then local vehicle = g_currentMission.nodeToVehicle[otherId]; if vehicle ~= nil then local enterTable = true; for i=1, table.getn(self.vehicleInTrigger) do if self.vehicleInTrigger[i] == vehicle then enterTable = false; end; end; if enterTable then vehicle.isInSilo = true; table.insert(self.vehicleInTrigger, vehicle) end; end; elseif onLeave then local vehicle = g_currentMission.nodeToVehicle[otherId]; if vehicle ~= nil then for i=1, table.getn(self.vehicleInTrigger) do if self.vehicleInTrigger[i] == vehicle then vehicle.isInSilo = false; table.remove(self.vehicleInTrigger, i) end; end; end; end; end; function MapBGASilo:shovelGetCallback(triggerId, otherId, onEnter, onLeave, onStay, otherShapeId) if (onEnter or onLeave) then local shovel = g_currentMission.nodeToVehicle[otherShapeId]; if shovel ~= nil then if onLeave then if self.currentShovel == shovel and self.currentShovelNode == otherShapeId then self.currentShovel = nil; self.currentShovelNode = nil; end else if shovel.allowFillFromShovelTrigger and shovel.fillShovelFromTrigger ~= nil and (shovel.shovelNodes == nil or shovel.shovelNodes[otherShapeId]) then self.currentShovel = shovel; self.currentShovelNode = otherShapeId; end; end; end; end; end; function MapBGASilo:updateDriveDown(dt) -- updateTick if table.getn(self.vehicleInTrigger) > 0 then local massOfMovingVehicle = 0; local gesMassOfVehicle = 0; local gesDistance = 0; local removeVehicleFillLevelMass = 0; for i=1, table.getn(self.vehicleInTrigger) do local vehicle = self.vehicleInTrigger[i]; if vehicle ~= nil then if vehicle.isDeleted then vehicle.isInSilo = nil; table.remove(self.vehicleInTrigger, i); break; end; --vehicle.isInSilo = true; if vehicle.headyBGASiloFound ~= nil then if vehicle.headyBGASiloFound then if vehicle.fillLevel ~= nil and vehicle.currentFillType ~= nil then if vehicle.fillLevel > 0 and self.allowFillTypes[vehicle.currentFillType] then local roh = Fillable.fillTypeIndexToDesc[vehicle.currentFillType].massPerLiter; removeVehicleFillLevelMass = removeVehicleFillLevelMass + roh*vehicle.fillLevel; end; end; --[[if vehicle.lastSpeed*3600 > 3 then -- kmh = self.lastSpeed*3600; for vi=1, table.getn(vehicle.components) do local vehicleComponent = vehicle.components[vi]; if vehicleComponent.node ~= nil then massOfMovingVehicle = massOfMovingVehicle + getMass(vehicleComponent.node); end; end; end;]] for vi=1, table.getn(vehicle.components) do local vehicleComponent = vehicle.components[vi]; if vehicleComponent.node ~= nil then gesMassOfVehicle = gesMassOfVehicle + getMass(vehicleComponent.node)*Utils.getNoNil(vehicle.bunkerSiloCompactingScale, 1); end; end; local vx, vy, vz = worldDirectionToLocal(vehicle.components[1].node, getLinearVelocity(vehicle.components[1].node)); local lastSpeedReal = Utils.vector3Length(vx, vy, vz)*0.001; local lastMovedDistance = lastSpeedReal*dt; gesDistance = gesDistance + lastMovedDistance; end; end; end; end; local value = gesDistance*(gesMassOfVehicle-removeVehicleFillLevelMass)*self.compScale; self.compFillLevel = self.compFillLevel + value; if self.compFillLevel >= self.silage.fillLevel then self.compFillLevel = self.silage.fillLevel; end; if value > 0 then self.doUpdateCompFillLevel = true; end; end; end; function MapBGASilo:getPlayerShowInfo() if g_currentMission.controlPlayer and self.playerInRange and not g_currentMission.isPlayerFrozen and g_gui.currentGui == nil then return true; end; return false; end; function MapBGASilo:getVehicleShowInfo() if not g_currentMission.controlPlayer then for _, vehicle in pairs(self.vehicleInTrigger) do if vehicle:getIsActiveForInput(false) then return true; end; end; end; return false; end; function MapBGASilo:updateSendEvent() if g_server ~= nil then g_server:broadcastEvent(MPEvent:new(self)); else g_client:getServerConnection():sendEvent(MPEvent:new(self)); end; end; function MapBGASilo:updateSendEventPrintDebug() if g_server ~= nil then --g_server:broadcastEvent(MPEvent:new(self)); else g_client:getServerConnection():sendEvent(PrintDebugMPEvent:new(self)); end; end; local VehicleUpdateTick = Vehicle.updateTick; Vehicle.updateTick = function(self, dt) VehicleUpdateTick(self, dt); if self.isInSilo ~= nil then if self.isInSilo then self.headyBGASiloFound = nil; local x,y,z = getWorldTranslation(self.components[1].node); raycastAll(x, y+1, z, 0, -1, 0, "findSiloColiRaycastCallback", 5, self); end; end; end; Vehicle.findSiloColiRaycastCallback = function(self, transformId, x, y, z, distance) local object = g_currentMission:getNodeObject(transformId); if object ~= nil and object ~= self and object.isHeadyBGASilo ~= nil then if object.isHeadyBGASilo then self.headyBGASiloFound = true; end; end; return true; end;