local metadata = { "## Interface:FS15 1.1.0.0 RC12", "## Title: MilchTransport", "## Notes: Zum Transport und Verkauf von Milch", "## Author: Marhu", "## Version: 4.0.3 for ROS Box", "## Date: 06.05.2015", } source(g_currentModDirectory.."store/MilchTrailerSetIsFillingEvent.lua"); source(g_currentModDirectory.."store/MilchTriggerCallbackEvent.lua"); g_MilchTransportDir = g_currentModDirectory; MilchTransport = {}; MilchTransport.MilktruckFillTrigger = {} MilchTransport.MilktruckStartTrigger = {} if MilktruckFillTrigger.onCreate ~= nil then local orgFillTriggerOnCreate = MilktruckFillTrigger.onCreate; MilktruckFillTrigger.onCreate = function(a,id) orgFillTriggerOnCreate(a,id); table.insert(MilchTransport.MilktruckFillTrigger,id); end; end; if MilktruckFillTrigger.delete ~= nil then local orgFillTriggerdelete = MilktruckFillTrigger.delete; MilktruckFillTrigger.delete = function(a) for i = 1, table.getn(MilchTransport.MilktruckFillTrigger) do if MilchTransport.MilktruckFillTrigger[i] == a.triggerId then table.remove(MilchTransport.MilktruckFillTrigger,i); break; end; end; orgFillTriggerdelete(a); end; end; if MilktruckStartTrigger.onCreate ~= nil then local orgStartTriggerOnCreate = MilktruckStartTrigger.onCreate; MilktruckStartTrigger.onCreate = function(a,id) orgStartTriggerOnCreate(a,id); table.insert(MilchTransport.MilktruckStartTrigger,id); end; end; if MilktruckStartTrigger.delete ~= nil then local orgStartTriggerdelete = MilktruckStartTrigger.delete; MilktruckStartTrigger.delete = function(a) for i = 1, table.getn(MilchTransport.MilktruckStartTrigger) do if MilchTransport.MilktruckStartTrigger[i] == a.triggerId then table.remove(MilchTransport.MilktruckStartTrigger,i); break; end; end; orgStartTriggerdelete(a); end; end; if MilktruckFillTrigger.triggerCallback ~= nil then local orgtriggerCallback = MilktruckFillTrigger.triggerCallback; MilktruckFillTrigger.triggerCallback = function(a, triggerId, otherId, onEnter, onLeave, onStay, otherShapeId) orgtriggerCallback(a, triggerId, otherId, onEnter, onLeave, onStay, otherShapeId); local MilkTrailer = g_currentMission.objectToTrailer[otherShapeId]; if MilkTrailer ~= nil and MilkTrailer.addMilchTrailerFillTrigger ~= nil and MilkTrailer.removeMilchTrailerFillTrigger ~= nil then if onEnter then MilkTrailer:addMilchTrailerFillTrigger({id = triggerId, fillMilk = true}, g_server ~= nil); else -- onLeave MilkTrailer:removeMilchTrailerFillTrigger({id = triggerId, fillMilk = true}, g_server ~= nil); end; end; end; end; if MilktruckStartTrigger.triggerCallback ~= nil then local orgtriggerCallback = MilktruckStartTrigger.triggerCallback; MilktruckStartTrigger.triggerCallback = function(a, triggerId, otherId, onEnter, onLeave, onStay, otherShapeId) orgtriggerCallback(a, triggerId, otherId, onEnter, onLeave, onStay, otherShapeId); local MilkTrailer = g_currentMission.objectToTrailer[otherShapeId]; if MilkTrailer ~= nil and MilkTrailer.addMilchTrailerFillTrigger ~= nil and MilkTrailer.removeMilchTrailerFillTrigger ~= nil then if onEnter then MilkTrailer:addMilchTrailerFillTrigger({id = triggerId, buyMilk = true}, g_server ~= nil); else -- onLeave MilkTrailer:removeMilchTrailerFillTrigger({id = triggerId, buyMilk = true}, g_server ~= nil); end; end; end; end; function MilchTransport.prerequisitesPresent(specializations) return true end; function MilchTransport:load(xmlFile) self.TriggerCallback = MilchTransport.TriggerCallback; self.setIsMilchTrailerFilling = SpecializationUtil.callSpecializationsFunction("setIsMilchTrailerFilling"); self.setIsMilchTrailerBuyMilk = SpecializationUtil.callSpecializationsFunction("setIsMilchTrailerBuyMilk"); self.setIsZuchtFilling = SpecializationUtil.callSpecializationsFunction("setIsZuchtFilling"); self.removeMilchTrailerFillTrigger = SpecializationUtil.callSpecializationsFunction("removeMilchTrailerFillTrigger"); self.addMilchTrailerFillTrigger = SpecializationUtil.callSpecializationsFunction("addMilchTrailerFillTrigger"); self.isMilchTrailerFilling = false; self.isMilchTrailerBuyMilk = false; self.isZuchtFilling = false; self.milchTrailerActivatableAdded = false; self.milchTrailerActivatable = MilchTrailerActivatable:new(self); self.MilchTrailerFillTriggers = {}; self.fillLitersPerSecond = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.fillLitersPerSecond"), 500); local TrailerFillTriggerNode = Utils.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.milkTrailerFillTrigger#index")); if TrailerFillTriggerNode ~= nil then self.TrailerFillTrigger = TrailerFillTriggerNode; addTrigger(self.TrailerFillTrigger, "TriggerCallback", self); end; self.fillSoundEnabled = false; local fillSound = getXMLString(self.xmlFile, "vehicle.fillSound#file"); if fillSound ~= nil and fillSound ~= "" then fillSound = Utils.getFilename(fillSound, g_MilchTransportDir); self.fillSound = createSample("fillSound"); loadSample(self.fillSound, fillSound, false); self.fillSoundPitchOffset = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.fillSound#pitchOffset"), 1.0); self.fillSoundVolume = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.fillSound#volume"), 1.0); setSamplePitch(self.fillSound, self.fillSoundPitchOffset); end; self.AddMarkierung = not Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.MilktruckTrigger#AddMarkierung"), false); -- if not g_currentMission.fillTypeOverlays[Fillable.FILLTYPE_MILK] then -- --local ow = g_currentMission.fillTypeOverlays[1]; -- --g_currentMission.fillTypeOverlays[Fillable.FILLTYPE_MILK] = Overlay:new("milk", g_MilchTransportDir.."milk.dds", ow.x, ow.y, ow.width, ow.height); -- end -- if not g_currentMission.husbandries.cow.fillLevelMilk and -- g_currentMission.husbandries.cow.fillLevels and -- g_currentMission.husbandries.cow.fillLevels[Fillable.FILLTYPE_MILK] then -- self.NoPatch = true; -- end end; function MilchTransport:delete() if self.TrailerFillTrigger then removeTrigger(self.TrailerFillTrigger); self.TrailerFillTrigger = nil; end if self.milchTrailerActivatableAdded then g_currentMission:removeActivatableObject(self.milchTrailerActivatable); self.milchTrailerActivatableAdded = false; end; if self.fillSound ~= nil then delete(self.fillSound); end; end; function MilchTransport:mouseEvent(posX, posY, isDown, isUp, button) end; function MilchTransport:keyEvent(unicode, sym, modifier, isDown) end; function MilchTransport:update(dt) if self:getIsActiveForInput() then if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA2) then if g_currentMission.MilktruckTriggerMarkierung and table.getn(g_currentMission.MilktruckTriggerMarkierung) > 0 then local vis = not getVisibility(g_currentMission.MilktruckTriggerMarkierung[1]) for i = 1, table.getn(g_currentMission.MilktruckTriggerMarkierung) do setVisibility(g_currentMission.MilktruckTriggerMarkierung[i],vis) end; end; end; end; end; function MilchTransport:updateTick(dt) if not self.AddMarkierung and not g_currentMission.MilktruckTriggerMarkierung then self.AddMarkierung = true g_currentMission.MilktruckTriggerMarkierung = {} if MilchTransport.MilktruckFillTrigger then for i = 1, table.getn(MilchTransport.MilktruckFillTrigger) do local MarkierungRoot = getChildAt(Utils.loadSharedI3DFile(g_MilchTransportDir.."store/Markierung.i3d"), 0); if MarkierungRoot then link(getRootNode(), MarkierungRoot); local x, y, z = getWorldTranslation(MilchTransport.MilktruckFillTrigger[i]); y = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, y, z); setTranslation(MarkierungRoot, x, y, z); setVisibility(MarkierungRoot,false) table.insert(g_currentMission.MilktruckTriggerMarkierung,MarkierungRoot) end; end; MilchTransport.MilktruckFillTrigger = {}; end if MilchTransport.MilktruckStartTrigger then for i = 1, table.getn(MilchTransport.MilktruckStartTrigger) do local MarkierungRoot = getChildAt(Utils.loadSharedI3DFile(g_MilchTransportDir.."store/Markierung.i3d"), 0); if MarkierungRoot then link(getRootNode(), MarkierungRoot); local x, y, z = getWorldTranslation(MilchTransport.MilktruckStartTrigger[i]); y = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, y, z); setTranslation(MarkierungRoot, x, y, z); setVisibility(MarkierungRoot,false) table.insert(g_currentMission.MilktruckTriggerMarkierung,MarkierungRoot) end; end; MilchTransport.MilktruckStartTrigger = {}; end; end; if self:getIsActive() or self.isMilchTrailerFilling or self.isMilchTrailerBuyMilk or self.isZuchtFilling then self.isNearMilktruckFillTrigger = nil self.isNearBuyMilkTrigger = nil self.isNearZuchtTrigger = nil for i=1, table.getn(self.MilchTrailerFillTriggers) do local trigger = self.MilchTrailerFillTriggers[i]; if trigger.fillMilk then self.isNearMilktruckFillTrigger = true; elseif trigger.buyMilk then self.isNearBuyMilkTrigger = true; elseif trigger.Zucht then self.isNearZuchtTrigger = trigger.Zucht; end break; end if self.isNearMilktruckFillTrigger or self.isNearBuyMilkTrigger or self.isNearZuchtTrigger then if not self.milchTrailerActivatableAdded then g_currentMission:addActivatableObject(self.milchTrailerActivatable); self.milchTrailerActivatableAdded = true; end; else if self.milchTrailerActivatableAdded then g_currentMission:removeActivatableObject(self.milchTrailerActivatable); self.milchTrailerActivatableAdded = false; end; end; if self.isServer then if self.isMilchTrailerFilling then if not self.isNearMilktruckFillTrigger then self:setIsMilchTrailerFilling(false); end end if self.isMilchTrailerBuyMilk then if not self.isNearBuyMilkTrigger then self:setIsMilchTrailerBuyMilk(false); end end if self.isZuchtFilling then if not self.isNearZuchtTrigger then self:setIsZuchtFilling(false); end end if self.isMilchTrailerFilling then local delta = self.fillLitersPerSecond*dt*0.001; if self:allowFillType(Fillable.FILLTYPE_MILK, false) then local milk = 0 if self.NoPatch then milk = g_currentMission.husbandries.cow.fillLevels[Fillable.FILLTYPE_MILK] else milk = g_currentMission.husbandries.cow.fillLevelMilk or 0 end delta = math.min(milk,delta) local oldFillLevel = self:getFillLevel(Fillable.FILLTYPE_MILK); self:setFillLevel(oldFillLevel + delta, Fillable.FILLTYPE_MILK, true); delta = self:getFillLevel(Fillable.FILLTYPE_MILK) - oldFillLevel; if self.NoPatch then g_currentMission.husbandries.cow.fillLevels[Fillable.FILLTYPE_MILK] = milk - delta else g_currentMission.husbandries.cow.fillLevelMilk = milk - delta end else delta = 0; end if delta <= 0 then self:setIsMilchTrailerFilling(false); end; elseif self.isMilchTrailerBuyMilk then local delta = self.fillLitersPerSecond*dt*0.001; local oldFillLevel = self:getFillLevel(Fillable.FILLTYPE_MILK); delta = math.min(oldFillLevel,delta) self:setFillLevel(oldFillLevel - delta, Fillable.FILLTYPE_MILK, true); delta = self:getFillLevel(Fillable.FILLTYPE_MILK) - oldFillLevel; local difficultyMultiplier = math.max(2 * (3 - g_currentMission.missionStats.difficulty), 1); -- 1 2 4 local price = Fillable.fillTypeIndexToDesc[Fillable.FILLTYPE_MILK].pricePerLiter * difficultyMultiplier * delta; g_currentMission:addSharedMoney(-price); if delta >= 0 then self:setIsMilchTrailerBuyMilk(false); end; elseif self.isZuchtFilling then local delta = self.fillLitersPerSecond*dt*0.001; delta = math.min(self:getFillLevel(Fillable.FILLTYPE_MILK),delta) local oldFillLevel = self.isNearZuchtTrigger:getFillLevel(Fillable.FILLTYPE_MILK); self.isNearZuchtTrigger:setFillLevel(oldFillLevel + delta, Fillable.FILLTYPE_MILK); delta = self.isNearZuchtTrigger:getFillLevel(Fillable.FILLTYPE_MILK) - oldFillLevel; self:setFillLevel(self:getFillLevel(Fillable.FILLTYPE_MILK) - delta, Fillable.FILLTYPE_MILK, true); if delta <= 0 then self:setIsZuchtFilling(false); end; end; end; end if self.isClient then if self.isMilchTrailerFilling or self.isMilchTrailerBuyMilk or self.isZuchtFilling then if not self.fillSoundEnabled and self.fillSound ~= nil and self:getIsActiveForSound() then playSample(self.fillSound, 0, self.fillSoundVolume, 0); self.fillSoundEnabled = true; end; else if self.fillSoundEnabled then stopSample(self.fillSound); self.fillSoundEnabled = false; end; end; end; end function MilchTransport:readStream(streamId, connection) if connection:getIsServer() then end; end; function MilchTransport:writeStream(streamId, connection) if not connection:getIsServer() then end; end; function MilchTransport:readUpdateStream(streamId, timestamp, connection) if connection:getIsServer() then if self.isMilchTrailerFilling then fillLevel = streamReadFloat32(streamId); if fillLevel and fillLevel > 0 then if self.NoPatch then g_currentMission.husbandries.cow.fillLevels[Fillable.FILLTYPE_MILK] = fillLevel else g_currentMission.husbandries.cow.fillLevelMilk = fillLevel end end end end end; function MilchTransport:writeUpdateStream(streamId, connection, dirtyMask) if not connection:getIsServer() then if self.isMilchTrailerFilling then local milk = 0 if self.NoPatch then milk = g_currentMission.husbandries.cow.fillLevels[Fillable.FILLTYPE_MILK] else milk = g_currentMission.husbandries.cow.fillLevelMilk end streamWriteFloat32(streamId, milk); end end end; function MilchTransport:draw() if self.isClient then -- if self.fillLevel <= 0 and self.capacity ~= 0 then -- g_currentMission:addExtraPrintText(g_i18n:getText("FirstFillTheTool")); -- end; -- if self.currentFillType ~= Fillable.FILLTYPE_UNKNOWN then -- g_currentMission:setFillTypeOverlayFillType(self.currentFillType); -- end; if g_currentMission.MilktruckTriggerMarkierung and table.getn(g_currentMission.MilktruckTriggerMarkierung) > 0 then if getVisibility(g_currentMission.MilktruckTriggerMarkierung[1]) then g_currentMission:addHelpButtonText(g_i18n:getText("Hidde_Marker"), InputBinding.IMPLEMENT_EXTRA2); else g_currentMission:addHelpButtonText(g_i18n:getText("Show_Marker"), InputBinding.IMPLEMENT_EXTRA2); end end end; end; function MilchTransport:onAttach() end; function MilchTransport:onDetach() if self.milchTrailerActivatableAdded then g_currentMission:removeActivatableObject(self.milchTrailerActivatable); self.milchTrailerActivatableAdded = false; end; if self.fillSoundEnabled then stopSample(self.fillSound); self.fillSoundEnabled = false; end; end; function MilchTransport:onLeave() if self.milchTrailerActivatableAdded then g_currentMission:removeActivatableObject(self.milchTrailerActivatable); self.milchTrailerActivatableAdded = false; end; if self.fillSoundEnabled then stopSample(self.fillSound); self.fillSoundEnabled = false; end; end function MilchTransport:getSaveAttributesAndNodes(nodeIdent) local attributes = ""; local nodes = ""; return attributes,nodes; end function MilchTransport:loadFromAttributesAndNodes(self.xmlFile, key, resetVehicles) return BaseMission.VEHICLE_LOAD_OK; end function MilchTransport:setIsMilchTrailerFilling(isFilling, noEventSend) MilchTrailerSetIsFillingEvent.sendEvent(self, isFilling, self.isMilchTrailerBuyMilk, self.isZuchtFilling, noEventSend) self.isMilchTrailerFilling = isFilling; end; function MilchTransport:setIsMilchTrailerBuyMilk(isBy, noEventSend) MilchTrailerSetIsFillingEvent.sendEvent(self, self.isMilchTrailerFilling, isBy, self.isZuchtFilling, noEventSend) self.isMilchTrailerBuyMilk = isBy; end; function MilchTransport:setIsZuchtFilling(isFilling, noEventSend) MilchTrailerSetIsFillingEvent.sendEvent(self, self.isMilchTrailerFilling, self.isMilchTrailerBuyMilk, isFilling, noEventSend) self.isZuchtFilling = isFilling; end; function MilchTransport:addMilchTrailerFillTrigger(trigger, send, noEventSend) table.insert(self.MilchTrailerFillTriggers, trigger); if send then MilchTriggerCallbackEvent.sendEvent(self, trigger.id, trigger.fillMilk, true, noEventSend) end --print("addMilchTrailerFillTrigger ",table.getn(self.MilchTrailerFillTriggers)) end; function MilchTransport:removeMilchTrailerFillTrigger(trigger, send, noEventSend) for i=1, table.getn(self.MilchTrailerFillTriggers) do if self.MilchTrailerFillTriggers[i].id == trigger.id then table.remove(self.MilchTrailerFillTriggers, i); break; end; end; if send then MilchTriggerCallbackEvent.sendEvent(self, trigger.id, trigger.fillMilk, false, noEventSend) end --print("removeMilchTrailerFillTrigger ",table.getn(self.MilchTrailerFillTriggers)) end; function MilchTransport:TriggerCallback(triggerId, otherId, onEnter, onLeave, onStay, otherShapeId) local vehicle = g_currentMission.nodeToVehicle[otherId]; if vehicle ~= nil then if vehicle.milktruckStopNode then if onEnter then self:addMilchTrailerFillTrigger({id = otherId, buyMilk = true}); else -- onLeave self:removeMilchTrailerFillTrigger({id = otherId, buyMilk = true}); end; elseif vehicle ~= self and vehicle.addMilchTrailerFillTrigger ~= nil and vehicle.addMilchTrailerFillTrigger ~= nil then if onEnter then vehicle:addMilchTrailerFillTrigger({id = triggerId, Zucht = self}); else -- onLeave vehicle:removeMilchTrailerFillTrigger({id = triggerId, Zucht = self}); end; end; end; end; MilchTrailerActivatable = {} local MilchTrailerActivatable_mt = Class(MilchTrailerActivatable); function MilchTrailerActivatable:new(trailer) local self = {}; setmetatable(self, MilchTrailerActivatable_mt); self.trailer = trailer; self.activateText = "unknown"; local overlay = Utils.getFilename("store/overlay.png", g_MilchTransportDir); self.Overlay = Overlay:new("OverloadOverlay", overlay, g_currentMission.hudTipperOverlay.x, g_currentMission.hudTipperOverlay.y, g_currentMission.hudTipperOverlay.width, g_currentMission.hudTipperOverlay.height); return self; end; function MilchTrailerActivatable:getIsActivatable() if self.trailer:getIsActiveForInput() then if self.trailer.isNearMilktruckFillTrigger and self.trailer:getFillLevel(Fillable.FILLTYPE_MILK) < self.trailer.capacity and self.trailer:allowFillType(Fillable.FILLTYPE_MILK, false) then self:updateActivateText(); return true; elseif (self.trailer.isNearBuyMilkTrigger or self.trailer.isNearZuchtTrigger) and self.trailer:getFillLevel(Fillable.FILLTYPE_MILK) > 0 then self:updateActivateText(); return true; end end return false; end function MilchTrailerActivatable:onActivateObject() if self.trailer.isNearMilktruckFillTrigger then self.trailer:setIsMilchTrailerFilling(not self.trailer.isMilchTrailerFilling); elseif self.trailer.isNearBuyMilkTrigger then self.trailer:setIsMilchTrailerBuyMilk(not self.trailer.isMilchTrailerBuyMilk); elseif self.trailer.isNearZuchtTrigger then self.trailer:setIsZuchtFilling(not self.trailer.isZuchtFilling); end self:updateActivateText(); g_currentMission:addActivatableObject(self); end; function MilchTrailerActivatable:drawActivate() self.Overlay:render(); end; function MilchTrailerActivatable:updateActivateText() if self.trailer.isNearMilktruckFillTrigger then if self.trailer.isMilchTrailerFilling then self.activateText = string.format(g_i18n:getText("stop_refill_OBJECT"), self.trailer.typeDesc); else self.activateText = string.format(g_i18n:getText("refill_OBJECT"), self.trailer.typeDesc); end; elseif self.trailer.isNearBuyMilkTrigger then if self.trailer.isMilchTrailerBuyMilk then self.activateText = g_i18n:getText("stop_selling"); else self.activateText = g_i18n:getText("sell_milk"); end; elseif self.trailer.isNearZuchtTrigger then if self.trailer.isZuchtFilling then self.activateText = string.format(g_i18n:getText("stop_refill_OBJECT"), g_i18n:getText("Milk_storage")); else self.activateText = string.format(g_i18n:getText("refill_OBJECT"), g_i18n:getText("Milk_storage")); end; end; end;