From c6d23f30870b4a5b8105792ab6be81c91d022bc3 Mon Sep 17 00:00:00 2001 From: Moon Horse Date: Sat, 21 Dec 2024 19:44:51 +0300 Subject: [PATCH] Added previous pneumatics version for compatibility with 3rd party 81-717/714 train types --- lua/entities/gmod_subway_base/init.lua | 2 +- .../systems/sys_81_714_new_pneumatic.lua | 35 +- .../systems/sys_81_714_pneumatic.lua | 706 +++++++++++++++ .../systems/sys_81_717_new_pneumatic.lua | 41 +- .../systems/sys_81_717_pneumatic.lua | 830 ++++++++++++++++++ lua/metrostroi/systems/sys_pr_14x_panels.lua | 2 +- lua/metrostroi_data/languages/en_717.lua | 10 +- 7 files changed, 1583 insertions(+), 43 deletions(-) create mode 100644 lua/metrostroi/systems/sys_81_714_pneumatic.lua create mode 100644 lua/metrostroi/systems/sys_81_717_pneumatic.lua diff --git a/lua/entities/gmod_subway_base/init.lua b/lua/entities/gmod_subway_base/init.lua index 1cae98c..cd8ea42 100644 --- a/lua/entities/gmod_subway_base/init.lua +++ b/lua/entities/gmod_subway_base/init.lua @@ -2210,7 +2210,7 @@ function ENT:ButtonEvent(button,state,ply) if ShouldFireEvents(self.ButtonBuffer[button],state) then if state == false and not self:OnButtonRelease(button,ply) then self:TriggerInput(button,0.0) - if button:match("LineIsolationToggle") then self:UpdateIsolationConnectedCarCounter(button:sub(-24,-20)) end + if button:match("LineIsolationToggle") and self.CarCount then self:UpdateIsolationConnectedCarCounter(button:sub(-24,-20)) end elseif state ~= false and not self:OnButtonPress(button,ply) then self:TriggerInput(button,1.0) if self.Plombs and button:sub(-2,-1) == "Pl" and self.Plombs[button:sub(1,-3)] then diff --git a/lua/metrostroi/systems/sys_81_714_new_pneumatic.lua b/lua/metrostroi/systems/sys_81_714_new_pneumatic.lua index 65e8f44..786129c 100644 --- a/lua/metrostroi/systems/sys_81_714_new_pneumatic.lua +++ b/lua/metrostroi/systems/sys_81_714_new_pneumatic.lua @@ -33,10 +33,9 @@ function TRAIN_SYSTEM:Initialize(parameters) -- Pressure in trains feed line self.TrainLinePressure = 8.0 -- atm -- Pressure in trains brake line - self.BrakeLinePressure = 0.0 -- atm + self.BrakeLinePressure = 3.0 -- atm -- Pressure in brake cylinder self.BrakeCylinderPressure = 0.0 -- atm - self.OldBrakeLinePressure = 0.0 -- Pressure in the door line self.DoorLinePressure = 0.0 -- atm self.LeftDoorCloseCylPressure = 0.0 @@ -49,11 +48,11 @@ function TRAIN_SYSTEM:Initialize(parameters) self.OldBrakeLinePressure = 0.0 self.BCPressure = 0 -- Air distrubutor part - self.WorkingChamberPressure = 0.0 + self.WorkingChamberPressure = 5.2 -- Disconnected KM 334 vessels (trainline and brakeline parts between disconnect valve and KM itself) emulation self.TLDisconnectPressure = 0.0 self.BLDisconnectPressure = 0.0 - self.WCChargeValve = true + self.WCChargeValve = false self.PN1 = 0 self.PN2 = 0 self.cranPres = 0 @@ -518,32 +517,32 @@ function TRAIN_SYSTEM:Think(dT) end -- 013: 2 Normal pressure - if (self.RealDriverValvePosition == 2) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > 1.01*math.min(self.KM013offset,self.TrainToBrakeReducedPressure)) then--was pr_speed*2 - self:equalizePressure(dT,"BrakeLinePressure", 1.01*math.min(self.KM013offset+(self.km13_error2 or 0),self.TrainLinePressure), pr_speed, pz_speed, nil, 2.5)-- nil, 1.0) + if (self.RealDriverValvePosition == 2) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > math.min(self.KM013offset,self.TrainToBrakeReducedPressure)) then--was pr_speed*2 + self:equalizePressure(dT,"BrakeLinePressure", math.min(self.KM013offset+(self.km13_error2 or 0),self.TrainLinePressure), pr_speed, pz_speed, nil, 2.5)-- nil, 1.0) if self.km13_error2 and self.BrakeLinePressure >= self.KM013offset+self.km13_error2-0.1 then - self:equalizePressure(dT,"BrakeLinePressure", 1.01*math.min(self.KM013offset,self.TrainToBrakeReducedPressure), 35, pz_speed, nil, 1) + self:equalizePressure(dT,"BrakeLinePressure", math.min(self.KM013offset,self.TrainToBrakeReducedPressure), 35, pz_speed, nil, 1) self.km13_error2 = nil end end -- 013: 3 4.3 Atm - if (self.RealDriverValvePosition == 3) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > 1.01*math.min(4.3,self.TrainToBrakeReducedPressure)) then - self:equalizePressure(dT,"BrakeLinePressure", 1.01*math.min(4.3,self.TrainToBrakeReducedPressure), pr_speed,pz_speed, nil, 2.5) + if (self.RealDriverValvePosition == 3) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > math.min(4.3,self.TrainToBrakeReducedPressure)) then + self:equalizePressure(dT,"BrakeLinePressure", math.min(4.3,self.TrainToBrakeReducedPressure), pr_speed,pz_speed, nil, 2.5) end -- 013: 4 4.0 Atm - if (self.RealDriverValvePosition == 4) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > 1.01*math.min(4.0,self.TrainToBrakeReducedPressure)) then - self:equalizePressure(dT,"BrakeLinePressure", 1.01*math.min(4.0,self.TrainToBrakeReducedPressure), pr_speed,pz_speed, nil, 2.5) + if (self.RealDriverValvePosition == 4) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > math.min(4.0,self.TrainToBrakeReducedPressure)) then + self:equalizePressure(dT,"BrakeLinePressure", math.min(4.0,self.TrainToBrakeReducedPressure), pr_speed,pz_speed, nil, 2.5) end -- 013: 5 3.7 Atm - if (self.RealDriverValvePosition == 5) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > 1.01*math.min(3.7,self.TrainToBrakeReducedPressure)) then - self:equalizePressure(dT,"BrakeLinePressure", 1.01*math.min(3.7,self.TrainToBrakeReducedPressure), pr_speed,pz_speed, nil, 2.5) + if (self.RealDriverValvePosition == 5) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > math.min(3.7,self.TrainToBrakeReducedPressure)) then + self:equalizePressure(dT,"BrakeLinePressure", math.min(3.7,self.TrainToBrakeReducedPressure), pr_speed,pz_speed, nil, 2.5) end -- 013: 6 3.0 Atm - if (self.RealDriverValvePosition == 6) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > 1.01*math.min(3.0,self.TrainToBrakeReducedPressure)) then - self:equalizePressure(dT,"BrakeLinePressure", 1.01*math.min(3.0,self.TrainToBrakeReducedPressure), pr_speed,pz_speed, nil, 2.5) + if (self.RealDriverValvePosition == 6) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > math.min(3.0,self.TrainToBrakeReducedPressure)) then + self:equalizePressure(dT,"BrakeLinePressure", math.min(3.0,self.TrainToBrakeReducedPressure), pr_speed,pz_speed, nil, 2.5) end -- 013: 7 0.0 Atm @@ -802,8 +801,10 @@ function TRAIN_SYSTEM:Think(dT) lmOpen = Train[m..tostring(9-i)].Value > 0 rmClose = Train[n..i].Value > 0 lmClose = Train[n..tostring(9-i)].Value > 0 - self.LeftDoorState[i] = math.Clamp(self.LeftDoorState[i] + (not llocked and ((lmOpen and 1.5 or lmClose and -1.5 or 0) + (self.DoorLinePressure > 1.0 and (math.Round(self.LeftDoorOpenCylPressure - self.LeftDoorCloseCylPressure,1))*0.36*(not (lmOpen or lmClose) and self.LeftDoorSpeed[i] or 1) or 0))*dT or 0),self.LeftDoorStuck[i] and 0.3 or 0,1) - self.RightDoorState[i] = math.Clamp(self.RightDoorState[i] + (not rlocked and ((rmOpen and 1.5 or rmClose and -1.5 or 0) + (self.DoorLinePressure > 1.0 and (math.Round(self.RightDoorOpenCylPressure - self.RightDoorCloseCylPressure,1))*0.36*(not (rmOpen or rmClose) and self.RightDoorSpeed[i] or 1) or 0))*dT or 0),self.RightDoorStuck[i] and 0.3 or 0,1) + --self.LeftDoorState[i] = math.Clamp(self.LeftDoorState[i] + (not llocked and ((lmOpen and 1.5 or lmClose and -1.5 or 0) + (self.DoorLinePressure > 1.0 and (math.Round(self.LeftDoorOpenCylPressure - self.LeftDoorCloseCylPressure,1))*0.36*(not (lmOpen or lmClose) and self.LeftDoorSpeed[i] or 1) or 0))*dT or 0),self.LeftDoorStuck[i] and 0.3 or 0,1) + --self.RightDoorState[i] = math.Clamp(self.RightDoorState[i] + (not rlocked and ((rmOpen and 1.5 or rmClose and -1.5 or 0) + (self.DoorLinePressure > 1.0 and (math.Round(self.RightDoorOpenCylPressure - self.RightDoorCloseCylPressure,1))*0.36*(not (rmOpen or rmClose) and self.RightDoorSpeed[i] or 1) or 0))*dT or 0),self.RightDoorStuck[i] and 0.3 or 0,1) + self.LeftDoorState[i] = math.Clamp(self.LeftDoorState[i] + (not llocked and ((lmOpen and 1.5 or lmClose and -1.5 or 0) + (self.DoorLinePressure > 1.0 and (self.LeftDoorOpenCylPressure - self.LeftDoorCloseCylPressure)*0.36*(not (lmOpen or lmClose) and self.LeftDoorSpeed[i] or 1) or 0))*dT or 0),self.LeftDoorStuck[i] and 0.3 or 0,1) + self.RightDoorState[i] = math.Clamp(self.RightDoorState[i] + (not rlocked and ((rmOpen and 1.5 or rmClose and -1.5 or 0) + (self.DoorLinePressure > 1.0 and (self.RightDoorOpenCylPressure - self.RightDoorCloseCylPressure)*0.36*(not (rmOpen or rmClose) and self.RightDoorSpeed[i] or 1) or 0))*dT or 0),self.RightDoorStuck[i] and 0.3 or 0,1) if not Train.LeftDoorsOpen and self.LeftDoorState[i] > 0.02 then --was 0.06 Train.LeftDoorsOpen = true end diff --git a/lua/metrostroi/systems/sys_81_714_pneumatic.lua b/lua/metrostroi/systems/sys_81_714_pneumatic.lua new file mode 100644 index 0000000..8d9c0b1 --- /dev/null +++ b/lua/metrostroi/systems/sys_81_714_pneumatic.lua @@ -0,0 +1,706 @@ +-------------------------------------------------------------------------------- +-- 81-714 pneumatic system +-------------------------------------------------------------------------------- +-- Copyright (C) 2013-2018 Metrostroi Team & FoxWorks Aerospace s.r.o. +-- Contains proprietary code. See license.txt for additional information. +-------------------------------------------------------------------------------- +Metrostroi.DefineSystem("81_714_Pneumatic") +TRAIN_SYSTEM.DontAccelerateSimulation = true + +function TRAIN_SYSTEM:Initialize(parameters) + self.ValveType = 1 + -- Position of the train drivers valve + -- Type 1 (334) + -- 1 Accelerated charge + -- 2 Normal charge (brake release) + -- 3 Closed + -- 4 Service application + -- 5 Emergency application + -- + -- Type 2 (013) + -- 1 Accelerated charge + -- 2 Normal charge (brake release) + -- 3 Closed + -- 4 Service application + -- 5 Emergency application + self.DriverValvePosition = 2 + self.RealDriverValvePosition = self.DriverValvePosition + + + -- Pressure in reservoir + self.ParkingBrakePressure = 0 + self.ReservoirPressure = 0.0 -- atm + -- Pressure in trains feed line + self.TrainLinePressure = 8.0 -- atm + -- Pressure in trains brake line + self.BrakeLinePressure = 3.0 -- atm + -- Pressure in brake cylinder + self.BrakeCylinderPressure = 0.0 -- atm + self.OldBrakeLinePressure = 3.0 + -- Pressure in the door line + self.DoorLinePressure = 0.0 -- atm + self.BCPressure = 0 + -- Air distrubutor part + self.WorkingChamberPressure = 5.2 + -- Disconnected KM 334 vessels (trainline and brakeline parts between disconnect valve and KM itself) emulation + self.TLDisconnectPressure = 0.0 + self.BLDisconnectPressure = 0.0 + self.WCChargeValve = false + self.PN1 = 0 + self.PN2 = 0 + self.cranPres = 0 + self.KM013offset = 5.2 + + --DKPT + self.Train:LoadSystem("DKPT","Relay","R-52B") -- + -- Valve #1 + self.Train:LoadSystem("PneumaticNo1","Relay") + -- Valve #2 + self.Train:LoadSystem("PneumaticNo2","Relay") + -- Автоматический выключатель торможения (АВТ) + self.Train:LoadSystem("AVT","Relay","AVT-325") + -- Регулятор давления (АК) + self.Train:LoadSystem("AK","Relay","AK-11B") + -- Блокировка тормозов + self.Train:LoadSystem("BPT","Relay","") + -- Блокировка дверей + self.Train:LoadSystem("BD","Relay","") + -- Вентили дверного воздухораспределителя (ВДОЛ, ВДОП, ВДЗ) + self.Train:LoadSystem("VDOL","Relay","", {bass = true}) + self.Train:LoadSystem("VDOP","Relay","", {bass = true}) + self.Train:LoadSystem("VDZ","Relay","", {bass = true}) + + -- Краны двойной тяги + self.Train:LoadSystem("DriverValveTLDisconnect","Relay","Switch", {bass = true}) + self.Train:LoadSystem("DriverValveBLDisconnect","Relay","Switch", {bass = true}) + + self.Train:LoadSystem("EmergencyBrakeValve","Relay","Switch") + -- Воздухораспределитель + self.Train:LoadSystem("AirDistributorDisconnect","Relay","Switch") + --Стояночный тормоз + self.Train:LoadSystem("ParkingBrake","Relay","Switch",{bass = true}) + -- Isolation valves + self.Train:LoadSystem("FrontBrakeLineIsolation","Relay","Switch", { normally_closed = true, bass = true}) + self.Train:LoadSystem("RearBrakeLineIsolation","Relay","Switch", { normally_closed = true, bass = true}) + self.Train:LoadSystem("FrontTrainLineIsolation","Relay","Switch", { normally_closed = true, bass = true}) + self.Train:LoadSystem("RearTrainLineIsolation","Relay","Switch", { normally_closed = true, bass = true}) + + -- Brake cylinder atmospheric valve open + self.BrakeCylinderValve = 0 + + -- Overpressure protection valve open + self.TrainLineOverpressureValve = 0 + + -- Compressor simulation + self.Compressor = 0 --Simulate overheat with TRK FIXME + + -- Doors state + if not TURBOSTROI then + self.LeftDoorState = { 0,0,0,0 } + self.RightDoorState = { 0,0,0,0 } + self.LeftDoorDir = { 0,0,0,0 } + self.RightDoorDir = { 0,0,0,0 } + self.LeftDoorSpeed = {0,0,0,0} + self.RightDoorSpeed = {0,0,0,0} + local start = math.Rand(0.6,0.8) + -- 0.6-1 + self.DoorSpeedMain = -math.Rand(start,math.Rand(start+0.1,start+0.2)) + for i=1,#self.LeftDoorSpeed do + if math.random() > 0.7 then + self.LeftDoorSpeed[i] = math.Rand(self.DoorSpeedMain-0.1,self.DoorSpeedMain+0.2) + self.RightDoorSpeed[i] = math.Rand(self.DoorSpeedMain-0.1,self.DoorSpeedMain+0.2) + else + self.LeftDoorSpeed[i] = math.Rand(self.DoorSpeedMain-0.1,self.DoorSpeedMain+0.1) + self.RightDoorSpeed[i] = math.Rand(self.DoorSpeedMain-0.1,self.DoorSpeedMain+0.1) + end + end + end + self.TrainLineOpen = false + self.BrakeLineOpen = false + + self.BLDisconnect = true + self.TLDisconnect = true + + self.OldValuePos = self.DriverValvePosition + + self.WeightLoadRatio = 0 + self.PassengerDoor = 0 +end + +function TRAIN_SYSTEM:Inputs() + return { "BrakeUp", "BrakeDown", "BrakeSet", "ValveType", "Autostop", "KM013offset" } +end + +function TRAIN_SYSTEM:Outputs() + return { "BrakeLinePressure", "BrakeCylinderPressure", "DriverValvePosition", "WorkingChamberPressure", + "ReservoirPressure", "TrainLinePressure", "DoorLinePressure", "WeightLoadRatio" } +end + +function TRAIN_SYSTEM:TriggerInput(name,value) + if name == "BrakeSet" then + self.DriverValvePosition = math.floor(value) + if self.ValveType == 1 then + if self.DriverValvePosition < 1 then self.DriverValvePosition = 1 end + if self.DriverValvePosition > 5 then self.DriverValvePosition = 5 end + else + if self.DriverValvePosition < 1 then self.DriverValvePosition = 1 end + if self.DriverValvePosition > 7 then self.DriverValvePosition = 7 end + end + elseif (name == "BrakeUp") and (value > 0.5) then + self:TriggerInput("BrakeSet",self.DriverValvePosition+1) + elseif (name == "BrakeDown") and (value > 0.5) then + self:TriggerInput("BrakeSet",self.DriverValvePosition-1) + elseif name == "ValveType" then + self.ValveType = math.floor(value) + elseif name == "KM013offset" then + self.KM013offset = value + elseif name:match("VZ%dOffset") then + local idx = name:match("VZ(%d)Offset") + self["GN"..idx.."Offset"] = math.random(2,10)*0.02 + value + self["GN"..idx.."Start"] = value + --PrintMessage(HUD_PRINTTALK, Format("Вагон %u; ВЗ-1: %.1f; ВЗ-2: %.1f",self.Train:GetWagonNumber(),self.GN1Offset or 0,self.GN2Offset or 0)) + end +end + + +-- TODO: почистить это говно, сделать раздельные звуки пневмы +-- Calculate derivatives +function TRAIN_SYSTEM:equalizeCouplePressure(dT,pressure,train,valve_status,rate,close_rate) + if not valve_status then return 0 end + local other + if IsValid(train) then other = train.Pneumatic end + + -- Get second pressure + local P2 = 0 + if other then P2 = other[pressure] end + if (not other) and (valve_status) then + self.TrainLineOpen = (pressure == "TrainLinePressure") + rate = close_rate or rate + --self.TrainLinePressure_dPdT = 0.0 + end + + -- Calculate rate + local dPdT = rate * (P2 - self[pressure]) + -- Calculate delta + local dP = dPdT*dT + if other and other.ReadOnly then + dP = dP/250 + end + -- Equalized pressure + local P0 = (P2 + self[pressure]) / 2 + -- Update pressures + if dP > 0 then + self[pressure] = math.min(P0,self[pressure] + dP) + if other and not other.ReadOnly then + other[pressure] = math.max(P0,other[pressure] - dP) + end + else + self[pressure] = math.max(P0,self[pressure] + dP) + if other and not other.ReadOnly then + other[pressure] = math.min(P0,other[pressure] - dP) + end + end + -- Update delta if losing air + if self.TrainLineOpen and (pressure == "TrainLinePressure") then + self[pressure.."_dPdT"] = (self[pressure.."_dPdT"] or 0) + dPdT + end + return dP +end +------------------------------------------------------------------------------- +function TRAIN_SYSTEM:UpdatePressures(Train,dT) + local frontBrakeOpen = Train.FrontBrakeLineIsolation.Value == 0 + local rearBrakeOpen = Train.RearBrakeLineIsolation.Value == 0 + local frontTrainOpen = Train.FrontTrainLineIsolation.Value == 0 + local rearTrainOpen = Train.RearTrainLineIsolation.Value == 0 + + local Ft = IsValid(Train.FrontTrain) and Train.FrontTrain + local Rt = IsValid(Train.RearTrain) and Train.RearTrain + local Fc, Rc = Train.FrontCouple or Train.FrontBogey, Train.RearCouple or Train.RearBogey + local Fb,Rb + if IsValid(Fc) and Fc.DepotPneumo then Fb = Fc.DepotPneumo end + if IsValid(Rc) and Rc.DepotPneumo then Rb = Rc.DepotPneumo end + + local frontBrakeLeak = false + local rearBrakeLeak = false + local frontTrainLeak = false + local rearTrainLeak = false + + -- Check if both valve on this train and connected train are open + if Ft and Ft.FrontBrakeLineIsolation then + if Ft.FrontTrain == Train then -- Nose to nose + frontBrakeLeak = frontBrakeOpen and Ft.FrontBrakeLineIsolation.Value==1 and 0.08 + frontTrainLeak = frontTrainOpen and Ft.FrontTrainLineIsolation.Value==1 and 0.08 + else -- Rear to nose + frontBrakeLeak = frontBrakeOpen and Ft.RearBrakeLineIsolation.Value==1 and 0.08 + frontTrainLeak = frontTrainOpen and Ft.RearTrainLineIsolation.Value==1 and 0.08 + end + else + frontBrakeLeak = frontBrakeOpen and 0.7 + frontTrainLeak = frontTrainOpen and not Fb and 0.3 + end + if Rt and Rt.FrontBrakeLineIsolation then + if Rt.FrontTrain == Train then -- Nose to nose + rearBrakeLeak = rearBrakeOpen and Rt.FrontBrakeLineIsolation.Value==1 and 0.08 + rearTrainLeak = rearTrainOpen and Rt.FrontTrainLineIsolation.Value==1 and 0.08 + else -- Rear to nose + rearBrakeLeak = rearBrakeOpen and Rt.RearBrakeLineIsolation.Value==1 and 0.08 + rearTrainLeak = rearTrainOpen and Rt.RearTrainLineIsolation.Value==1 and 0.08 + end + else + rearBrakeLeak = rearBrakeOpen and 0.7 + rearTrainLeak = rearTrainOpen and not Rb and 0.3 + end + + -- Equalize pressure + local Fl=math.min(0,self:equalizeCouplePressure(dT,"BrakeLinePressure",frontBrakeLeak==false and Ft,frontBrakeOpen,50,frontBrakeLeak or 0.08)*3)*(frontBrakeLeak and 1 or 0) + local Rl=math.min(0,self:equalizeCouplePressure(dT,"BrakeLinePressure",rearBrakeLeak==false and Rt,rearBrakeOpen,50,rearBrakeLeak or 0.08)*3)*(rearBrakeLeak and 1 or 0) + + Fl=Fl+math.min(0,self:equalizeCouplePressure(dT,"TrainLinePressure",frontTrainLeak==false and Ft or Fb,frontTrainOpen,100,frontTrainLeak or 0.08)*10)*(frontTrainLeak and 1 or 0) + Rl=Rl+math.min(0,self:equalizeCouplePressure(dT,"TrainLinePressure",rearTrainLeak==false and Rt or Rb,rearTrainOpen,100,rearTrainLeak or 0.08)*10)*(rearTrainLeak and 1 or 0) + + self.TrainLineOpen=frontTrainLeak or rearTrainLeak + self.BrakeLineOpen=frontBrakeLeak or rearBrakeLeak + Train:SetPackedRatio("FrontLeak",Fl) + Train:SetPackedRatio("RearLeak",Rl) +end + +function TRAIN_SYSTEM:equalizePressure(dT,pressure,target,rate,fill_rate,no_limit,smooth) + if fill_rate and (target > self[pressure]) then rate = fill_rate end + + -- Calculate derivative + local dPdT = rate + if target < self[pressure] then dPdT = -dPdT end + local dPdTramp = math.min(1.0,math.abs(target - self[pressure])*(smooth or 0.5)) + dPdT = dPdT*dPdTramp + + -- Update pressure + self[pressure] = self[pressure] + dT * dPdT + self[pressure] = math.max(0.0,math.min(16.0,self[pressure])) + self[pressure.."_dPdT"] = (self[pressure.."_dPdT"] or 0) + dPdT + if no_limit ~= true then + if self[pressure] == 0.0 then self[pressure.."_dPdT"] = 0 end + if self[pressure] == 16.0 then self[pressure.."_dPdT"] = 0 end + end + return dPdT +end +------------------------------------------------------------------------------- +function TRAIN_SYSTEM:Think(dT) + local Train = self.Train + local retainer = Train:GetNW2Int("RetainerLoad", 4) + self.WeightLoadRatio = retainer == 4 and math.max(0,math.min(1,(Train:GetNW2Float("PassengerCount")/200))) or (retainer-1)*0.5 + + ---------------------------------------------------------------------------- + -- Accumulate derivatives + self.TrainLinePressure_dPdT = 0.0 + self.BrakeLinePressure_dPdT = 0.0 + self.ReservoirPressure_dPdT = 0.0 + self.BrakeCylinderPressure_dPdT = 0.0 + self.ParkingBrakePressure_dPdT = 0.0 + self.WorkingChamberPressure_dPdT = 0.0 + + -- Reduce pressure for brake line + self.TrainToBrakeReducedPressure = math.min(self.KM013offset,self.TrainLinePressure) -- * 0.725) + -- Feed pressure to door line + self.DoorLinePressure = self.TrainToBrakeReducedPressure * 0.90 + local trainLineConsumption_dPdT = 0.0 + local wagc = Train.CarCount and Train:GetBLConnectedWagonCount() or #Train.WagonList + local HaveEPK = not Train.SubwayTrain or not Train.SubwayTrain.ARS or not Train.SubwayTrain.ARS.NoEPK + + local pr_speed = 1 + + if self.ValveType == 1 then + self.BLDisconnect = Train.DriverValveBLDisconnect.Value > 0 + self.TLDisconnect = Train.DriverValveTLDisconnect.Value > 0 and self.RealDriverValvePosition ~= 3 + pr_speed = 1*wagc--*((self.BrakeLinePressure-self.ReservoirPressure)/0.6) --2 + if self.TLDisconnect then self.TLDisconnectPressure = self.TrainLinePressure end + if self.Leak or self.BrakeLineOpen then pr_speed = pr_speed*0.3 end + -- 334: 1 Fill reservoir from train line, fill brake line from train line + if (self.RealDriverValvePosition == 1) then + if self.TLDisconnect or self.ReservoirPressure ~= self.TLDisconnectPressure then + if self.BLDisconnect then + self.ReservoirPressure = self.BrakeLinePressure + self:equalizePressure(dT,"BrakeLinePressure", self.TLDisconnectPressure, pr_speed*(pr_speed < wagc and 1 or 1.35),nil,nil,2)--0.7 + else + self:equalizePressure(dT,"ReservoirPressure", self.TLDisconnectPressure, 3.55,nil,nil,2) + end + end + end + + -- 334: 2 Brake line, reservoir replenished from brake line reductor + if (self.RealDriverValvePosition == 2) then + if self.TLDisconnect then + local a = 1 + if --[[self.EmergencyValve or ]]Train.EmergencyBrakeValve.Value > 0.5 then a = 1.85 end + if self.BLDisconnect then + self.ReservoirPressure = self.BrakeLinePressure + self:equalizePressure(dT,"BrakeLinePressure", self.TrainToBrakeReducedPressure, pr_speed*0, pr_speed*0.6*a, nil, 1.6) + self.ReservoirPressure_dPdT = self.BrakeLinePressure_dPdT*0.8 + else + self:equalizePressure(dT,"ReservoirPressure", self.TrainToBrakeReducedPressure,0,1.55,nil,2) + end + end + end + + -- 334: 3 Close all valves + if (self.RealDriverValvePosition == 3) then + -- Typical leak + self:equalizePressure(dT,"ReservoirPressure", 0.00, 0.001) + end + + local res_dischrg_rate4 = self.BLDisconnect and 0.55 or 8 + local res_dischrg_rate5 = self.BLDisconnect and 1.12 or 8 + -- 334: 4 Reservoir open to atmosphere, brake line equalizes with reservoir + if (self.RealDriverValvePosition == 4) then + self:equalizePressure(dT,"ReservoirPressure", 0.0, res_dischrg_rate4, nil,nil,6)--0.35)-0.55 + end + + -- 334: 5 Reservoir and brake line open to atmosphere + if (self.RealDriverValvePosition == 5) then + self:equalizePressure(dT,"ReservoirPressure", 0.0, res_dischrg_rate5)--,nil,nil,2)--1.70 + local pr_speed = 1.25*wagc + if self.Leak or self.BrakeLineOpen then pr_speed = pr_speed*0.3 end + if self.BLDisconnect then + if self.Leak then pr_speed = pr_speed*6.2 end + self:equalizePressure(dT,"BrakeLinePressure", 0.0, pr_speed,nil,nil,2) + end + end + -- утечка через неплотность уравнительного поршня + if self.BLDisconnect then self:equalizePressure(dT, "ReservoirPressure", self.BrakeLinePressure, 0.06, 0) end + if (self.RealDriverValvePosition > 2) and (self.RealDriverValvePosition < 5) then + local pr_speed = 1.25*wagc + if self.Leak or self.BrakeLineOpen then pr_speed = pr_speed*0.3 end + local _a = 0 + for _i = 1, #Train.WagonList do + if Train.WagonList[_i].Pneumatic.TLDisconnect and Train.WagonList[_i].Pneumatic.BLDisconnect and (Train.WagonList[_i].Pneumatic.RealDriverValvePosition == 2 or Train.WagonList[_i].Pneumatic.RealDriverValvePosition == 1) then + _a = _a + 1 + end + if _a > 0 then break end + end + if _a > 0 then pr_speed = pr_speed*0.1 end + if self.BLDisconnect and self.BrakeLinePressure - self.ReservoirPressure > (self.RealDriverValvePosition == 3 and 0 or self.RealDriverValvePosition == 4 and 0.2 or 100) then --0.2 bar is a piston sensitivity + self:equalizePressure(dT, "BrakeLinePressure", 0, pr_speed*math.abs(self.BrakeLinePressure - self.ReservoirPressure), nil, nil, 6) + end + end + + if not self.TLDisconnect then + self.TLDisconnectPressure = math.max(0,self.TLDisconnectPressure - math.abs(self.ReservoirPressure_dPdT)*dT) + end + self.ReservoirPressure_dPdT = self.ReservoirPressure_dPdT + self.BrakeLinePressure_dPdT*0.2 + Train:SetPackedRatio("ReservoirPressure_dPdT",self.ReservoirPressure_dPdT/wagc*2) + --[[ + ---------------debug--------------------- + self.dlreadtimer = self.dlreadtimer or CurTime() + if CurTime() - self.dlreadtimer > 1.0 then + self.dlreadtimer = CurTime() + if Train:GetDriver() then + PrintMessage(HUD_PRINTTALK, Format("Вагон %u; P ТМ: %.3f; P УР =%.3f; Утечка ТМ %.3f; TLDis = %.3f; pr_speed = %.3f",Train:GetWagonNumber(),self.BrakeLinePressure,self.ReservoirPressure,self.BrakeLinePressure_dPdT, self.TLDisconnectPressure, pr_speed)) + end + end + ---------------debug---------------------]] + trainLineConsumption_dPdT = trainLineConsumption_dPdT + math.max(0,self.BrakeLinePressure_dPdT) + trainLineConsumption_dPdT = trainLineConsumption_dPdT + math.max(0,self.ReservoirPressure_dPdT)*0.05 + else + pr_speed = 2.8--1.25*wagc --2 + local pz_speed + -- wagc | pr_speed + ------------------ + -- 1 | 8.455 + -- 2 | 7.865 + -- 3 | 7.376 + -- 4 | 6.969 + -- 5 | 6.627 + -- 6 | 6.341 + -- 7 | 6.100 + -- 8 | 5.900 + --pr_speed = (0.4*math.exp(0.1*wagc-1)+1)*160/(2*wagc+20) --2 + --local frc = 0.6--0.35 + if self.Leak or self.BrakeLineOpen then pz_speed = pr_speed*0.25 else pz_speed = pr_speed*1.3 end--*frc end + self.BLDisconnect = Train.DriverValveBLDisconnect.Value > 0 + self.TLDisconnect = Train.DriverValveTLDisconnect.Value > 0 + if self.RealDriverValvePosition > 4 and not self.km13_error2 then self.km13_error2 = 0.7 end + -- 013: 1 Overcharge + if (self.RealDriverValvePosition == 1) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > self.TrainLinePressure) then + self:equalizePressure(dT,"BrakeLinePressure", math.min(6.4,self.TrainLinePressure), pr_speed, pz_speed, nil, 1.0) + end + + -- 013: 2 Normal pressure + if (self.RealDriverValvePosition == 2) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > 1.01*math.min(self.KM013offset,self.TrainToBrakeReducedPressure)) then--was pr_speed*2 + self:equalizePressure(dT,"BrakeLinePressure", 1.01*math.min(self.KM013offset+(self.km13_error2 or 0),self.TrainLinePressure), pr_speed, pz_speed, nil, 2.5)-- nil, 1.0) + if self.km13_error2 and self.BrakeLinePressure >= self.KM013offset+self.km13_error2-0.1 then + self:equalizePressure(dT,"BrakeLinePressure", 1.01*math.min(self.KM013offset,self.TrainToBrakeReducedPressure), 35, pz_speed, nil, 1) + self.km13_error2 = nil + end + end + + -- 013: 3 4.3 Atm + if (self.RealDriverValvePosition == 3) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > 1.01*math.min(4.3,self.TrainToBrakeReducedPressure)) then + self:equalizePressure(dT,"BrakeLinePressure", 1.01*math.min(4.3,self.TrainToBrakeReducedPressure), pr_speed,pz_speed, nil, 2.5) + end + + -- 013: 4 4.0 Atm + if (self.RealDriverValvePosition == 4) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > 1.01*math.min(4.0,self.TrainToBrakeReducedPressure)) then + self:equalizePressure(dT,"BrakeLinePressure", 1.01*math.min(4.0,self.TrainToBrakeReducedPressure), pr_speed,pz_speed, nil, 2.5) + end + + -- 013: 5 3.7 Atm + if (self.RealDriverValvePosition == 5) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > 1.01*math.min(3.7,self.TrainToBrakeReducedPressure)) then + self:equalizePressure(dT,"BrakeLinePressure", 1.01*math.min(3.7,self.TrainToBrakeReducedPressure), pr_speed,pz_speed, nil, 2.5) + end + + -- 013: 6 3.0 Atm + if (self.RealDriverValvePosition == 6) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > 1.01*math.min(3.0,self.TrainToBrakeReducedPressure)) then + self:equalizePressure(dT,"BrakeLinePressure", 1.01*math.min(3.0,self.TrainToBrakeReducedPressure), pr_speed,pz_speed, nil, 2.5) + end + + -- 013: 7 0.0 Atm + if (self.RealDriverValvePosition == 7) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > 0.0) then + self:equalizePressure(dT,"BrakeLinePressure", 0.0, (0.6 + pr_speed*math.exp(math.min(0,self.BrakeLinePressure - 2.3)*1.0))*(0.15*wagc+1),pz_speed, nil, 2.5) + end + trainLineConsumption_dPdT = trainLineConsumption_dPdT + math.max(0,self.BrakeLinePressure_dPdT) + end + self.Leak = false + if wagc ~= Train.OldWagIsoCount or not Train.pr_spd_init then + pr_speed = (0.4*math.exp(0.1*wagc-1)+1)*160/(2*wagc+20) --2 + Train.OldWagIsoCount = wagc + Train.pr_spd_init = true + end + if self.ValveType == 1 then + Train:SetPackedRatio("Crane_dPdT", self.ReservoirPressure_dPdT ) + else + Train:SetPackedRatio("Crane_dPdT", self.BrakeLinePressure_dPdT/wagc*3 ) + end + + local leak = 0 + if Train.EmergencyBrakeValve and Train.EmergencyBrakeValve.Value > 0.5 then + local leakst = math.max(0.5,math.exp(0.5*self.BrakeLinePressure)) + leak = self:equalizePressure(dT,"BrakeLinePressure", 0.0,leakst)--,false,false,10) --was leakst*wagc/5 + self.Leak = true + end + Train:SetPackedRatio("EmergencyBrakeValve_dPdT", -leak/wagc) + ---------------------------------------------------------------------------- + -- Fill brake cylinders + if self.WCChargeValve == true then + self:equalizePressure(dT,"WorkingChamberPressure",self.BrakeLinePressure,0.094,nil,nil,1.0) --simulate 0.8mm hole btw BL and working chambers + end + local aird_ready = self.WorkingChamberPressure >= 2.2 + self.WCChargeValve = not ((self.WorkingChamberPressure - self.BrakeLinePressure) > 0.2 and (self.WorkingChamberPressure - self.BrakeLinePressure) < 2.5) + local KLSZ = self.WorkingChamberPressure > 5.2 and not self.WCChargeValve + if KLSZ then + self:equalizePressure(dT,"WorkingChamberPressure",0.0,0.12) -- КЛСЗ + end + + trainLineConsumption_dPdT = trainLineConsumption_dPdT + math.max(0,self.WorkingChamberPressure_dPdT*0.2) + self.GN2Offset = self.GN2Offset or math.random(20,100)*0.002 + (self.GN2Start or 2.4) + self.GN1Offset = self.GN1Offset or math.random(20,100)*0.002 + (self.GN1Start or 0.8) + self.BcBl = (self.GN2Offset + self.WeightLoadRatio*(self.GN2Offset - 1.4))/1.82--1.92 + if Train.AirDistributorDisconnect.Value == 0 and aird_ready then + -- Valve #1 + if (Train.PneumaticNo1.Value == 1.0) and (Train.PneumaticNo2.Value == 0.0) then + if self.PN1 < self.GN1Offset then + self.PN1 = math.min(self.TrainLinePressure,self.GN1Offset) + end + elseif Train.PneumaticNo1.Value == 0 and self.PN1 > 0.0 then + self.PN1 = self.BrakeCylinderPressure > 0.2 and 0.05 or self.PN1 - 0.5*dT + end + -- Valve #2 + if Train.PneumaticNo2.Value == 1.0 then + self.PN2 = math.min(self.TrainLinePressure,(self.GN2Offset + self.WeightLoadRatio*1.3)) + if self.BePN2 == false and self.BrakeCylinderPressure > 1.6 then + Train:PlayOnce("PN2end","stop") + end + self.BePN2 = true + elseif self.PN2 > 0.0 then + self.PN2 = self.BrakeCylinderPressure > 0.4 and 0.2 or self.PN2 - 0.5*dT + end + --[[ + ---------------debug--------------------- + self.brreadtimer = self.brreadtimer or CurTime() + if CurTime() - self.brreadtimer > 1.0 then + self.brreadtimer = CurTime() + if Train:GetDriver() then + --PrintMessage(HUD_PRINTTALK, Format("br_threshold = %.3f; WcBl = %s",br_threshold, tostring(WcBl))) + --PrintMessage(HUD_PRINTTALK, Format("Это %s", isLVZ and "ЛВЗ" or "не ЛВЗ")) + --PrintMessage(HUD_PRINTTALK, Format("Вагон %u; Авторежим: %.3f",Train:GetWagonNumber(),self.WeightLoadRatio)) + --PrintMessage(HUD_PRINTTALK, Format("wagc = %u; wagd = %u",wagc,wagd)) + end + end + ---------------debug---------------------]] + + self.BchExh = self.WorkingChamberPressure < 4.8 and self.BrakeLinePressure < 3.4 and 0 or 1 + self.cranPres = math.max(0,self.BcBl*(self.WorkingChamberPressure - self.BrakeLinePressure*self.BchExh)*(self.BrakeLinePressure > self.KM013offset and (0.6 + self.PN1*0.43) or 1)) + local targetPressure = math.max(0,math.min(self.GN2Offset + self.WeightLoadRatio*1.3, (self.cranPres < (self.PN1 + self.WeightLoadRatio*0.7) and (Train.PneumaticNo1.Value == 1.0) and (self.PN1 + self.WeightLoadRatio*0.7) or self.PN1) + self.PN2 + self.cranPres)) + if math.abs(self.BrakeCylinderPressure - targetPressure) > 0.150 then + self.BrakeCylinderValve = 1 + end + if math.abs(self.BrakeCylinderPressure - targetPressure) < 0.025 then + self.BrakeCylinderValve = 0 + end + if self.BrakeCylinderValve == 1 then + self:equalizePressure(dT,"BrakeCylinderPressure", math.min(self.GN2Offset + self.WeightLoadRatio*(self.GN2Offset - 1.4),targetPressure), 0.8, (Train.PneumaticNo1.Value > 0 or Train.PneumaticNo2.Value > 0) and 2.8 or 1.5, nil, 1.2) + end + trainLineConsumption_dPdT = trainLineConsumption_dPdT + math.max(0,self.BrakeCylinderPressure_dPdT*0.5) + elseif Train.AirDistributorDisconnect.Value ~= 0 then + self:equalizePressure(dT,"BrakeCylinderPressure", 0.0, 2.00) + end + if (self.BrakeCylinderPressure > 0.2 and self.BrakeCylinderPressure_dPdT > 0.1 or self.BrakeCylinderPressure_dPdT > 1) and not self.BrakeEngaged then + self.BrakeEngaged = true + Train:PlayOnce("brake","bass",1,math.Clamp(self.BrakeCylinderPressure_dPdT,0.7,1.2)) + end + if self.BrakeCylinderPressure < 1 and self.BrakeCylinderPressure_dPdT < -0.1 and self.BrakeEngaged then + self.BrakeEngaged = false + end + Train:SetPackedRatio("BrakeCylinderPressure_dPdT", self.BrakeCylinderPressure_dPdT) + self.TrainLinePressure = self.TrainLinePressure-math.max(0,self.BrakeCylinderPressure_dPdT*0.002) + if Train.PneumaticNo2.Value == 0 then + if self.BePN2 == true then + self.BePN2 = CurTime() + elseif self.BePN2 and self.BrakeCylinderPressure_dPdT > -0.2 then + Train:PlayOnce("PN2end","bass",math.Clamp(math.min(1,(CurTime()-self.BePN2)/1.3)*((3.2-self.BrakeCylinderPressure)/1.2),0,1)) + self.BePN2 = false + end + end + if self.BePN2 == false and (self.BrakeCylinderPressure_dPdT >= 0.2) then + self.BePN2 = nil + Train:PlayOnce("PN2end","stop") + end + + --Parking brake simulation + local PBPressure = math.Clamp(self.TrainLinePressure/5,0,1)*2.7 + if Train.ParkingBrake.Value == 0 then + self:equalizePressure(dT,"ParkingBrakePressure", PBPressure, 10,10,nil,0.5) + else + self:equalizePressure(dT,"ParkingBrakePressure", 0, 3,10,nil,0.5) + end + Train:SetPackedRatio("ParkingBrakePressure_dPdT",self.ParkingBrakePressure_dPdT) + trainLineConsumption_dPdT = trainLineConsumption_dPdT + math.max(0,self.ParkingBrakePressure_dPdT*0.5) + + -- Simulate cross-feed between different wagons + self:UpdatePressures(Train,dT) + + ---------------------------------------------------------------------------- + -- Simulate compressor operation and train line depletion + self.Compressor = Train.KK.Value * (Train.Electric.Aux750V > 550 and 1 or 0) + self.TrainLinePressure = self.TrainLinePressure - (Train.AirConsumeRatio or 0.06)*trainLineConsumption_dPdT*dT -- 0.190 --0.170 --0.07 + if self.Compressor == 1 then self:equalizePressure(dT,"TrainLinePressure", 10.0, Train.CompressorEfficiency or 0.07) end -- 0.04 + self:equalizePressure(dT,"TrainLinePressure", 0,Train.AirLeakRatio or 0.003) + -- Overpressure + if self.TrainLinePressure > math.max(7.2, (9.2 - self.TrainLineOverpressureValve*0.2)) and self.TrainLineOverpressureValve%2 == 0 then self.TrainLineOverpressureValve = self.TrainLineOverpressureValve + 1 end + if self.TrainLineOverpressureValve%2 == 1 then + self:equalizePressure(dT,"TrainLinePressure", 0.0, 0.2) + self.TrainLineOpen = true + if self.TrainLinePressure < 5.2 and self.TrainLineOverpressureValve < 20 then self.TrainLineOverpressureValve = self.TrainLineOverpressureValve + 1 end + end + + ---------------------------------------------------------------------------- + -- Pressure triggered relays + Train.AVT:TriggerInput("Open", self.BrakeCylinderPressure > 1.9) -- 1.8 - 2.0 + Train.AVT:TriggerInput("Close",self.BrakeCylinderPressure < 0.9) -- 0.9 - 1.5 + Train.AK:TriggerInput( "Open", self.TrainLinePressure > 8.2) + Train.AK:TriggerInput( "Close",self.TrainLinePressure < 6.3) + Train.BPT:TriggerInput("Set", (IsValid(Train.FrontBogey) and Train.FrontBogey.BrakeCylinderPressure+(not Train.FrontBogey.DisableParking and Train.FrontBogey.ParkingBrakePressure or 0) or self.BrakeCylinderPressure)>0.3) + Train.DKPT:TriggerInput("Set", self.BrakeCylinderPressure > 0.3) -- 1.8 - 2.0 + + ---------------------------------------------------------------------------- + -- Simulate doors opening, closing + if self.DoorLinePressure > 3.5 then + if (Train.VDOL.Value == 1.0) and (Train.VDOP.Value == 0.0) and not self.DoorLeft then + self.DoorLeft = true + if self.VDOLLoud then Train:PlayOnce("vdol_loud","cabin",0.8+math.random()*0.2,self.VDOLLoud) end + end + if (Train.VDOL.Value == 0.0) and (Train.VDOP.Value == 1.0) and not self.DoorRight then + self.DoorRight = true + if self.VDORLoud then Train:PlayOnce("vdop_loud","cabin",0.8+math.random()*0.2,self.VDORLoud) end + end + if (Train.VDZ.Value == 1.0 or Train.VDOL.Value == 1.0 and Train.VDOP.Value == 1.0 or self.RZDTimer) and (self.DoorLeft or self.DoorRight) then + if not self.OpenWaitL or CurTime()-self.OpenWaitL < 0.2 then + self.DoorLeft = false + end + if not self.OpenWaitR or CurTime()-self.OpenWaitR < 0.2 then + self.DoorRight = false + end + else + self.CloseValue = nil + end + if Train.VDOL.Value == 1.0 and Train.VDOP.Value == 1.0 then + self.RZDTimer = CurTime() + elseif self.RZDTimer and CurTime()-self.RZDTimer > 0.1 then + self.RZDTimer = nil + end + end + if self.VDOL ~= Train.VDOL.Value then + self.VDOL = Train.VDOL.Value + self:equalizePressure(dT,"TrainLinePressure", 0.0, 0.05) + end + if self.VDOP ~= Train.VDOP.Value then + self.VDOP = Train.VDOP.Value + self:equalizePressure(dT,"TrainLinePressure", 0.0, 0.05) + end + if self.VDZ ~= Train.VDZ.Value then + self.VDZ = Train.VDZ.Value + self:equalizePressure(dT,"TrainLinePressure", 0.0, 0.05) + end + + + Train.LeftDoorsOpen = false + Train.RightDoorsOpen = false + local openL = true + local openR = true + for i=1,4 do + self.LeftDoorDir[i] = math.Clamp(self.LeftDoorDir[i]+dT/(self.DoorLeft and self.LeftDoorSpeed[i] or -self.LeftDoorSpeed[i]),-1,1) + self.RightDoorDir[i] = math.Clamp(self.RightDoorDir[i]+dT/(self.DoorRight and self.RightDoorSpeed[i] or -self.RightDoorSpeed[i]),-1,1) + self.LeftDoorState[i] = math.Clamp(self.LeftDoorState[i] + ((self.LeftDoorDir[i]/self.LeftDoorSpeed[i])*dT),0,1) + if self.LeftDoorState[i] == 0 or self.LeftDoorState[i] == 1 then self.LeftDoorDir[i] = 0 end + self.RightDoorState[i] = math.Clamp(self.RightDoorState[i] + ((self.RightDoorDir[i]/self.RightDoorSpeed[i])*dT),0,1) + if self.RightDoorState[i] == 0 or self.RightDoorState[i] == 1 then self.RightDoorDir[i] = 0 end + if not Train.LeftDoorsOpen and self.LeftDoorState[i] > 0 then + Train.LeftDoorsOpen = true + end + if self.LeftDoorState[i] > self.LeftDoorSpeed[i]/20 then self.OpenWaitL = false end + if self.RightDoorState[i] > self.LeftDoorSpeed[i]/20 then self.OpenWaitR = false end + if self.LeftDoorState[i] > 0 then openL = false end + if self.RightDoorState[i] > 0 then openR = false end + if not Train.RightDoorsOpen and self.RightDoorState[i] > 0 then + Train.RightDoorsOpen = true + end + Train:SetPackedRatio("DoorL"..i,self.LeftDoorState[i]) + Train:SetPackedRatio("DoorR"..i,self.RightDoorState[i]) + end + if openL and not self.OpenWaitL then self.OpenWaitL = CurTime() end + if openR and not self.OpenWaitR then self.OpenWaitR = CurTime() end + Train:SetPackedBool("DoorL",self.DoorLeft) + Train:SetPackedBool("DoorR",self.DoorRight) + Train.BD:TriggerInput("Set",not Train.RightDoorsOpen and not Train.LeftDoorsOpen) + + ---------------------------------------------------------------------------- + -- FIXME + Train:SetNW2Bool("FbI",Train.FrontBrakeLineIsolation.Value ~= 0) + Train:SetNW2Bool("RbI",Train.RearBrakeLineIsolation.Value ~= 0) + Train:SetNW2Bool("FtI",Train.FrontTrainLineIsolation.Value ~= 0) + Train:SetNW2Bool("RtI",Train.RearTrainLineIsolation.Value ~= 0) + Train:SetNW2Bool("AD",Train.AirDistributorDisconnect.Value == 0) + + local ValveType = self.ValveType > 1 + self.Timer = self.Timer or CurTime() + if ((CurTime() - self.Timer > 0.10) and (self.DriverValvePosition > self.RealDriverValvePosition)) then + self.Timer = CurTime() + if not ValveType then + if self.RealDriverValvePosition ~= 3 then + Train:PlayOnce("br_334",self.RealDriverValvePosition.."-"..(self.RealDriverValvePosition+1)) + end + else + Train:PlayOnce("br_013","cabin") + end + self.RealDriverValvePosition = self.RealDriverValvePosition + 1 + end + if ((CurTime() - self.Timer > 0.10) and (self.DriverValvePosition < self.RealDriverValvePosition)) then + self.Timer = CurTime() + if not ValveType then + if self.RealDriverValvePosition ~= 5 then + Train:PlayOnce("br_334",self.RealDriverValvePosition.."-"..(self.RealDriverValvePosition-1)) + end + else + Train:PlayOnce("br_013","cabin") + end + self.RealDriverValvePosition = self.RealDriverValvePosition - 1 + end +end diff --git a/lua/metrostroi/systems/sys_81_717_new_pneumatic.lua b/lua/metrostroi/systems/sys_81_717_new_pneumatic.lua index 0300ebc..e0b0902 100644 --- a/lua/metrostroi/systems/sys_81_717_new_pneumatic.lua +++ b/lua/metrostroi/systems/sys_81_717_new_pneumatic.lua @@ -34,11 +34,10 @@ function TRAIN_SYSTEM:Initialize(parameters) -- Pressure in trains feed line self.TrainLinePressure = 8.0 -- atm -- Pressure in trains brake line - self.BrakeLinePressure = 0.0 -- atm + self.BrakeLinePressure = 3.0 -- atm self.EPKPressure = 0.0 -- atm -- Pressure in brake cylinder self.BrakeCylinderPressure = 0.0 -- atm - self.OldBrakeLinePressure = 0.0 -- Pressure in the door line self.DoorLinePressure = 0.0 -- atm self._1stRightDoorCloseCylPressure = 0.0 @@ -52,11 +51,11 @@ function TRAIN_SYSTEM:Initialize(parameters) self.OldBrakeLinePressure = 0.0 self.BCPressure = 0 -- Air distrubutor part - self.WorkingChamberPressure = 0.0 + self.WorkingChamberPressure = 5.2 -- Disconnected KM 334 vessels (trainline and brakeline parts between disconnect valve and KM itself) emulation self.TLDisconnectPressure = 0.0 self.BLDisconnectPressure = 0.0 - self.WCChargeValve = true + self.WCChargeValve = false self.PN1 = 0 self.PN2 = 0 self.cranPres = 0 @@ -576,32 +575,32 @@ function TRAIN_SYSTEM:Think(dT) end -- 013: 2 Normal pressure - if (self.RealDriverValvePosition == 2) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > 1.01*math.min(self.KM013offset,self.TrainToBrakeReducedPressure)) then--was pr_speed*2 - self:equalizePressure(dT,"BrakeLinePressure", 1.01*math.min(self.KM013offset+(self.km13_error2 or 0),self.TrainLinePressure), pr_speed, pz_speed, nil, 2.5)-- nil, 1.0) + if (self.RealDriverValvePosition == 2) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > math.min(self.KM013offset,self.TrainToBrakeReducedPressure)) then--was pr_speed*2 + self:equalizePressure(dT,"BrakeLinePressure", math.min(self.KM013offset+(self.km13_error2 or 0),self.TrainLinePressure), pr_speed, pz_speed, nil, 2.5)-- nil, 1.0) if self.km13_error2 and self.BrakeLinePressure >= self.KM013offset+self.km13_error2-0.1 then - self:equalizePressure(dT,"BrakeLinePressure", 1.01*math.min(self.KM013offset,self.TrainToBrakeReducedPressure), 35, pz_speed, nil, 1) + self:equalizePressure(dT,"BrakeLinePressure", math.min(self.KM013offset,self.TrainToBrakeReducedPressure), 35, pz_speed, nil, 1) self.km13_error2 = nil end end -- 013: 3 4.3 Atm - if (self.RealDriverValvePosition == 3) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > 1.01*math.min(4.3,self.TrainToBrakeReducedPressure)) then - self:equalizePressure(dT,"BrakeLinePressure", 1.01*math.min(4.3,self.TrainToBrakeReducedPressure), pr_speed,pz_speed, nil, 2.5) + if (self.RealDriverValvePosition == 3) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > math.min(4.3,self.TrainToBrakeReducedPressure)) then + self:equalizePressure(dT,"BrakeLinePressure", math.min(4.3,self.TrainToBrakeReducedPressure), pr_speed,pz_speed, nil, 2.5) end -- 013: 4 4.0 Atm - if (self.RealDriverValvePosition == 4) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > 1.01*math.min(4.0,self.TrainToBrakeReducedPressure)) then - self:equalizePressure(dT,"BrakeLinePressure", 1.01*math.min(4.0,self.TrainToBrakeReducedPressure), pr_speed,pz_speed, nil, 2.5) + if (self.RealDriverValvePosition == 4) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > math.min(4.0,self.TrainToBrakeReducedPressure)) then + self:equalizePressure(dT,"BrakeLinePressure", math.min(4.0,self.TrainToBrakeReducedPressure), pr_speed,pz_speed, nil, 2.5) end -- 013: 5 3.7 Atm - if (self.RealDriverValvePosition == 5) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > 1.01*math.min(3.7,self.TrainToBrakeReducedPressure)) then - self:equalizePressure(dT,"BrakeLinePressure", 1.01*math.min(3.7,self.TrainToBrakeReducedPressure), pr_speed,pz_speed, nil, 2.5) + if (self.RealDriverValvePosition == 5) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > math.min(3.7,self.TrainToBrakeReducedPressure)) then + self:equalizePressure(dT,"BrakeLinePressure", math.min(3.7,self.TrainToBrakeReducedPressure), pr_speed,pz_speed, nil, 2.5) end -- 013: 6 3.0 Atm - if (self.RealDriverValvePosition == 6) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > 1.01*math.min(3.0,self.TrainToBrakeReducedPressure)) then - self:equalizePressure(dT,"BrakeLinePressure", 1.01*math.min(3.0,self.TrainToBrakeReducedPressure), pr_speed,pz_speed, nil, 2.5) + if (self.RealDriverValvePosition == 6) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > math.min(3.0,self.TrainToBrakeReducedPressure)) then + self:equalizePressure(dT,"BrakeLinePressure", math.min(3.0,self.TrainToBrakeReducedPressure), pr_speed,pz_speed, nil, 2.5) end -- 013: 7 0.0 Atm @@ -913,11 +912,15 @@ function TRAIN_SYSTEM:Think(dT) lmOpen = Train[m..tostring(9-i)].Value > 0 rmClose = Train[n..i].Value > 0 lmClose = Train[n..tostring(9-i)].Value > 0 - self.LeftDoorState[i] = math.Clamp(self.LeftDoorState[i] + (not llocked and ((lmOpen and 1.5 or lmClose and -1.5 or 0) + - (self.DoorLinePressure > 1.0 and (math.Round(self.LeftDoorOpenCylPressure - self.LeftDoorCloseCylPressure,1))*0.36*(not (lmOpen or lmClose) and self.LeftDoorSpeed[i] or 1) or 0))*dT or 0),self.LeftDoorStuck[i] and 0.3 or 0,1) - self.RightDoorState[i] = math.Clamp(self.RightDoorState[i] + (not rlocked and ((rmOpen and 1.5 or rmClose and -1.5 or 0) + - (self.DoorLinePressure > 1.0 and (math.Round(self.RightDoorOpenCylPressure - (i == 1 and self._1stRightDoorCloseCylPressure or self.RightDoorCloseCylPressure),1))*0.36*(not (rmOpen or rmClose) and self.RightDoorSpeed[i] or 1) or 0))*dT or 0),self.RightDoorStuck[i] and 0.3 or 0,1) + --self.LeftDoorState[i] = math.Clamp(self.LeftDoorState[i] + (not llocked and ((lmOpen and 1.5 or lmClose and -1.5 or 0) + + -- (self.DoorLinePressure > 1.0 and (math.Round(self.LeftDoorOpenCylPressure - self.LeftDoorCloseCylPressure,1))*0.36*(not (lmOpen or lmClose) and self.LeftDoorSpeed[i] or 1) or 0))*dT or 0),self.LeftDoorStuck[i] and 0.3 or 0,1) + --self.RightDoorState[i] = math.Clamp(self.RightDoorState[i] + (not rlocked and ((rmOpen and 1.5 or rmClose and -1.5 or 0) + + -- (self.DoorLinePressure > 1.0 and (math.Round(self.RightDoorOpenCylPressure - (i == 1 and self._1stRightDoorCloseCylPressure or self.RightDoorCloseCylPressure),1))*0.36*(not (rmOpen or rmClose) and self.RightDoorSpeed[i] or 1) or 0))*dT or 0),self.RightDoorStuck[i] and 0.3 or 0,1) + self.LeftDoorState[i] = math.Clamp(self.LeftDoorState[i] + (not llocked and ((lmOpen and 1.5 or lmClose and -1.5 or 0) + + (self.DoorLinePressure > 1.0 and (self.LeftDoorOpenCylPressure - self.LeftDoorCloseCylPressure)*0.36*(not (lmOpen or lmClose) and self.LeftDoorSpeed[i] or 1) or 0))*dT or 0),self.LeftDoorStuck[i] and 0.3 or 0,1) + self.RightDoorState[i] = math.Clamp(self.RightDoorState[i] + (not rlocked and ((rmOpen and 1.5 or rmClose and -1.5 or 0) + + (self.DoorLinePressure > 1.0 and (self.RightDoorOpenCylPressure - (i == 1 and self._1stRightDoorCloseCylPressure or self.RightDoorCloseCylPressure))*0.36*(not (rmOpen or rmClose) and self.RightDoorSpeed[i] or 1) or 0))*dT or 0),self.RightDoorStuck[i] and 0.3 or 0,1) if not Train.LeftDoorsOpen and self.LeftDoorState[i] > 0.02 then --was 0.06 Train.LeftDoorsOpen = true end diff --git a/lua/metrostroi/systems/sys_81_717_pneumatic.lua b/lua/metrostroi/systems/sys_81_717_pneumatic.lua new file mode 100644 index 0000000..e991996 --- /dev/null +++ b/lua/metrostroi/systems/sys_81_717_pneumatic.lua @@ -0,0 +1,830 @@ +-------------------------------------------------------------------------------- +-- 81-717 pneumatic system +-------------------------------------------------------------------------------- +-- Copyright (C) 2013-2018 Metrostroi Team & FoxWorks Aerospace s.r.o. +-- Contains proprietary code. See license.txt for additional information. +-------------------------------------------------------------------------------- +Metrostroi.DefineSystem("81_717_Pneumatic") +TRAIN_SYSTEM.DontAccelerateSimulation = true + +function TRAIN_SYSTEM:Initialize(parameters) + self.ValveType = 1 + self.DisconnectType = parameters and parameters.br013_1 + -- Position of the train drivers valve + -- Type 1 (334) + -- 1 Accelerated charge + -- 2 Normal charge (brake release) + -- 3 Closed + -- 4 Service application + -- 5 Emergency application + -- + -- Type 2 (013) + -- 1 Accelerated charge + -- 2 Normal charge (brake release) + -- 3 Closed + -- 4 Service application + -- 5 Emergency application + self.DriverValvePosition = 2 + self.RealDriverValvePosition = self.DriverValvePosition + + + -- Pressure in reservoir + self.ParkingBrakePressure = 0 + self.ReservoirPressure = 0.0 -- atm + -- Pressure in trains feed line + self.TrainLinePressure = 8.0 -- atm + -- Pressure in trains brake line + self.BrakeLinePressure = 3.0 -- atm + self.EPKPressure = 0.0 -- atm + -- Pressure in brake cylinder + self.BrakeCylinderPressure = 0.0 -- atm + self.OldBrakeLinePressure = 3.0 + -- Pressure in the door line + self.DoorLinePressure = 0.0 -- atm + self.BCPressure = 0 + -- Air distrubutor part + self.WorkingChamberPressure = 5.2 + -- Disconnected KM 334 vessels (trainline and brakeline parts between disconnect valve and KM itself) emulation + self.TLDisconnectPressure = 0.0 + self.BLDisconnectPressure = 0.0 + self.WCChargeValve = false + self.PN1 = 0 + self.PN2 = 0 + self.cranPres = 0 + self.KM013offset = 5.2 + + --DKPT + self.Train:LoadSystem("DKPT","Relay","R-52B") -- + -- Valve #1 + self.Train:LoadSystem("PneumaticNo1","Relay") + -- Valve #2 + self.Train:LoadSystem("PneumaticNo2","Relay") + -- Автоматический выключатель торможения (АВТ) + self.Train:LoadSystem("AVT","Relay","AVT-325") + -- Регулятор давления (АК) + self.Train:LoadSystem("AK","Relay","AK-11B") + -- Автоматический выключатель управления (АВУ) + self.Train:LoadSystem("AVU","Relay","AVU-045") + -- Блокировка тормозов + self.Train:LoadSystem("BPT","Relay","") + -- Блокировка дверей + self.Train:LoadSystem("BD","Relay","") + -- Вентили дверного воздухораспределителя (ВДОЛ, ВДОП, ВДЗ) + self.Train:LoadSystem("VDOL","Relay","", {bass = true}) + self.Train:LoadSystem("VDOP","Relay","", {bass = true}) + self.Train:LoadSystem("VDZ","Relay","", {bass = true}) + + -- Разобщение клапана машиниста + self.Train:LoadSystem("DriverValveDisconnect","Relay","Switch", {bass = true}) + -- Краны двойной тяги + self.Train:LoadSystem("DriverValveTLDisconnect","Relay","Switch", {bass = true}) + self.Train:LoadSystem("DriverValveBLDisconnect","Relay","Switch", {bass = true}) + + self.Train:LoadSystem("EmergencyBrakeValve","Relay","Switch") + -- Воздухораспределитель + self.Train:LoadSystem("AirDistributorDisconnect","Relay","Switch") + --УАВА + self.Train:LoadSystem("UAVA","Relay","Switch",{ bass = true}) + self.Train:LoadSystem("UAVAContact","Relay","Switch") + self.Train:LoadSystem("UAVAC","Relay","",{normally_closed=true,bass=true}) + --Срывной клапан + self.Train:LoadSystem("AutostopValve","Relay","Switch") + --Стояночный тормоз + self.Train:LoadSystem("ParkingBrake","Relay","Switch",{bass = true}) + --ЭПК + self.Train:LoadSystem("EPK","Relay","Switch",{ bass = true}) + self.Train:LoadSystem("SOT","Relay") + -- Isolation valves + self.Train:LoadSystem("FrontBrakeLineIsolation","Relay","Switch", { normally_closed = true, bass = true}) + self.Train:LoadSystem("RearBrakeLineIsolation","Relay","Switch", { normally_closed = true, bass = true}) + self.Train:LoadSystem("FrontTrainLineIsolation","Relay","Switch", { normally_closed = true, bass = true}) + self.Train:LoadSystem("RearTrainLineIsolation","Relay","Switch", { normally_closed = true, bass = true}) + + self.Train:LoadSystem("SQ3","Relay","") + + -- Brake cylinder atmospheric valve open + self.BrakeCylinderValve = 0 + + -- Overpressure protection valve open + self.TrainLineOverpressureValve = 0 + + -- Compressor simulation + self.Compressor = 0 --Simulate overheat with TRK FIXME + + -- Disconnect valve status + self.DriverValveDisconnectPrevious = 0 + + -- Doors state + if not TURBOSTROI then + self.LeftDoorState = { 0,0,0,0 } + self.RightDoorState = { 0,0,0,0 } + self.LeftDoorDir = { 0,0,0,0 } + self.RightDoorDir = { 0,0,0,0 } + self.LeftDoorSpeed = {0,0,0,0} + self.RightDoorSpeed = {0,0,0,0} + local start = math.Rand(0.6,0.8) + -- 0.6-1 + self.DoorSpeedMain = -math.Rand(start,math.Rand(start+0.1,start+0.2)) + for i=1,#self.LeftDoorSpeed do + if math.random() > 0.7 then + self.LeftDoorSpeed[i] = math.Rand(self.DoorSpeedMain-0.1,self.DoorSpeedMain+0.2) + self.RightDoorSpeed[i] = math.Rand(self.DoorSpeedMain-0.1,self.DoorSpeedMain+0.2) + else + self.LeftDoorSpeed[i] = math.Rand(self.DoorSpeedMain-0.1,self.DoorSpeedMain+0.1) + self.RightDoorSpeed[i] = math.Rand(self.DoorSpeedMain-0.1,self.DoorSpeedMain+0.1) + end + end + end + self.TrainLineOpen = false + self.BrakeLineOpen = false + + self.BLDisconnect = true + self.TLDisconnect = true + + self.EmergencyValve = false + self.EmergencyValveEPK = false + self.OldValuePos = self.DriverValvePosition + + self.WeightLoadRatio = 0 + self.PassengerDoor = 0 +end + +function TRAIN_SYSTEM:Inputs() + return { "BrakeUp", "BrakeDown", "BrakeSet", "ValveType", "Autostop", "KM013offset" } +end + +function TRAIN_SYSTEM:Outputs() + return { "BrakeLinePressure", "BrakeCylinderPressure", "DriverValvePosition", "WorkingChamberPressure", + "ReservoirPressure", "TrainLinePressure", "DoorLinePressure", "WeightLoadRatio" } +end + +function TRAIN_SYSTEM:TriggerInput(name,value) + if name == "BrakeSet" then + self.DriverValvePosition = math.floor(value) + if self.ValveType == 1 then + if self.DriverValvePosition < 1 then self.DriverValvePosition = 1 end + if self.DriverValvePosition > 5 then self.DriverValvePosition = 5 end + else + if self.DriverValvePosition < 1 then self.DriverValvePosition = 1 end + if self.DriverValvePosition > 7 then self.DriverValvePosition = 7 end + end + elseif (name == "BrakeUp") and (value > 0.5) then + self:TriggerInput("BrakeSet",self.DriverValvePosition+1) + elseif (name == "BrakeDown") and (value > 0.5) then + self:TriggerInput("BrakeSet",self.DriverValvePosition-1) + elseif name == "ValveType" then + self.ValveType = math.floor(value) + elseif name:match("VZ%dOffset") then + local idx = name:match("VZ(%d)Offset") + self["GN"..idx.."Offset"] = math.random(2,10)*0.02 + value + self["GN"..idx.."Start"] = value + --PrintMessage(HUD_PRINTTALK, Format("Вагон %u; ВЗ-1: %.1f; ВЗ-2: %.1f",self.Train:GetWagonNumber(),self.GN1Offset or 0,self.GN2Offset or 0)) + elseif name == "KM013offset" then + self.KM013offset = value + elseif name == "Autostop" then + local HaveUAVA = not self.Train.SubwayTrain or not self.Train.SubwayTrain.ARS or not self.Train.SubwayTrain.ARS.NoUAVA + if HaveUAVA and self.Train.UAVA.Value == 0 then + self.EmergencyValve = true + if value ~= 2 then + self.Train.UAVAC:TriggerInput("Set",0) + if not self.Train.AutoStopNotify then + self.Train.AutoStopNotify = true + RunConsoleCommand("say","Autostop braking",self.Train:GetDriverName()) + end + end + end + end +end + + +-- TODO: почистить это говно, сделать раздельные звуки пневмы +-- Calculate derivatives +function TRAIN_SYSTEM:equalizeCouplePressure(dT,pressure,train,valve_status,rate,close_rate) + if not valve_status then return 0 end + local other + if IsValid(train) then other = train.Pneumatic end + + -- Get second pressure + local P2 = 0 + if other then P2 = other[pressure] end + if (not other) and (valve_status) then + self.TrainLineOpen = (pressure == "TrainLinePressure") + rate = close_rate or rate + --self.TrainLinePressure_dPdT = 0.0 + end + + -- Calculate rate + local dPdT = rate * (P2 - self[pressure]) + -- Calculate delta + local dP = dPdT*dT + if other and other.ReadOnly then + dP = dP/250 + end + -- Equalized pressure + local P0 = (P2 + self[pressure]) / 2 + -- Update pressures + if dP > 0 then + self[pressure] = math.min(P0,self[pressure] + dP) + if other and not other.ReadOnly then + other[pressure] = math.max(P0,other[pressure] - dP) + end + else + self[pressure] = math.max(P0,self[pressure] + dP) + if other and not other.ReadOnly then + other[pressure] = math.min(P0,other[pressure] - dP) + end + end + -- Update delta if losing air + if self.TrainLineOpen and (pressure == "TrainLinePressure") then + self[pressure.."_dPdT"] = (self[pressure.."_dPdT"] or 0) + dPdT + end + return dP +end +------------------------------------------------------------------------------- +function TRAIN_SYSTEM:UpdatePressures(Train,dT) + local frontBrakeOpen = Train.FrontBrakeLineIsolation.Value == 0 + local rearBrakeOpen = Train.RearBrakeLineIsolation.Value == 0 + local frontTrainOpen = Train.FrontTrainLineIsolation.Value == 0 + local rearTrainOpen = Train.RearTrainLineIsolation.Value == 0 + + local Ft = IsValid(Train.FrontTrain) and Train.FrontTrain + local Rt = IsValid(Train.RearTrain) and Train.RearTrain + local Fc, Rc = Train.FrontCouple or Train.FrontBogey, Train.RearCouple or Train.RearBogey + local Fb,Rb + if IsValid(Fc) and Fc.DepotPneumo then Fb = Fc.DepotPneumo end + if IsValid(Rc) and Rc.DepotPneumo then Rb = Rc.DepotPneumo end + + local frontBrakeLeak = false + local rearBrakeLeak = false + local frontTrainLeak = false + local rearTrainLeak = false + + -- Check if both valve on this train and connected train are open + if Ft and Ft.FrontBrakeLineIsolation then + if Ft.FrontTrain == Train then -- Nose to nose + frontBrakeLeak = frontBrakeOpen and Ft.FrontBrakeLineIsolation.Value==1 and 0.08 + frontTrainLeak = frontTrainOpen and Ft.FrontTrainLineIsolation.Value==1 and 0.08 + else -- Rear to nose + frontBrakeLeak = frontBrakeOpen and Ft.RearBrakeLineIsolation.Value==1 and 0.08 + frontTrainLeak = frontTrainOpen and Ft.RearTrainLineIsolation.Value==1 and 0.08 + end + else + frontBrakeLeak = frontBrakeOpen and 0.7 + frontTrainLeak = frontTrainOpen and not Fb and 0.3 + end + if Rt and Rt.FrontBrakeLineIsolation then + if Rt.FrontTrain == Train then -- Nose to nose + rearBrakeLeak = rearBrakeOpen and Rt.FrontBrakeLineIsolation.Value==1 and 0.08 + rearTrainLeak = rearTrainOpen and Rt.FrontTrainLineIsolation.Value==1 and 0.08 + else -- Rear to nose + rearBrakeLeak = rearBrakeOpen and Rt.RearBrakeLineIsolation.Value==1 and 0.08 + rearTrainLeak = rearTrainOpen and Rt.RearTrainLineIsolation.Value==1 and 0.08 + end + else + rearBrakeLeak = rearBrakeOpen and 0.7 + rearTrainLeak = rearTrainOpen and not Rb and 0.3 + end + + -- Equalize pressure + local Fl=math.min(0,self:equalizeCouplePressure(dT,"BrakeLinePressure",frontBrakeLeak==false and Ft,frontBrakeOpen,50,frontBrakeLeak or 0.08)*3)*(frontBrakeLeak and 1 or 0) + local Rl=math.min(0,self:equalizeCouplePressure(dT,"BrakeLinePressure",rearBrakeLeak==false and Rt,rearBrakeOpen,50,rearBrakeLeak or 0.08)*3)*(rearBrakeLeak and 1 or 0) + + Fl=Fl+math.min(0,self:equalizeCouplePressure(dT,"TrainLinePressure",frontTrainLeak==false and Ft or Fb,frontTrainOpen,100,frontTrainLeak or 0.08)*10)*(frontTrainLeak and 1 or 0) + Rl=Rl+math.min(0,self:equalizeCouplePressure(dT,"TrainLinePressure",rearTrainLeak==false and Rt or Rb,rearTrainOpen,100,rearTrainLeak or 0.08)*10)*(rearTrainLeak and 1 or 0) + + self.TrainLineOpen=frontTrainLeak or rearTrainLeak + self.BrakeLineOpen=frontBrakeLeak or rearBrakeLeak + Train:SetPackedRatio("FrontLeak",Fl) + Train:SetPackedRatio("RearLeak",Rl) +end + +function TRAIN_SYSTEM:equalizePressure(dT,pressure,target,rate,fill_rate,no_limit,smooth) + if fill_rate and (target > self[pressure]) then rate = fill_rate end + + -- Calculate derivative + local dPdT = rate + if target < self[pressure] then dPdT = -dPdT end + local dPdTramp = math.min(1.0,math.abs(target - self[pressure])*(smooth or 0.5)) + dPdT = dPdT*dPdTramp + + -- Update pressure + self[pressure] = self[pressure] + dT * dPdT + self[pressure] = math.max(0.0,math.min(16.0,self[pressure])) + self[pressure.."_dPdT"] = (self[pressure.."_dPdT"] or 0) + dPdT + if no_limit ~= true then + if self[pressure] == 0.0 then self[pressure.."_dPdT"] = 0 end + if self[pressure] == 16.0 then self[pressure.."_dPdT"] = 0 end + end + return dPdT +end +------------------------------------------------------------------------------- +function TRAIN_SYSTEM:Think(dT) + local Train = self.Train + local retainer = Train:GetNW2Int("RetainerLoad", 4) + self.WeightLoadRatio = retainer == 4 and math.max(0,math.min(1,(Train:GetNW2Float("PassengerCount")/200))) or (retainer-1)*0.5 + Train.Panel.UAVACOpened = (1-Train.UAVAC.Value)*((CurTime()-CurTime()%0.5)%1) + + ---------------------------------------------------------------------------- + -- Accumulate derivatives + self.TrainLinePressure_dPdT = 0.0 + self.BrakeLinePressure_dPdT = 0.0 + self.EPKPressure_dPdT = 0.0 + self.ReservoirPressure_dPdT = 0.0 + self.BrakeCylinderPressure_dPdT = 0.0 + self.ParkingBrakePressure_dPdT = 0.0 + self.WorkingChamberPressure_dPdT = 0.0 + + -- Reduce pressure for brake line + self.TrainToBrakeReducedPressure = math.min(self.KM013offset,self.TrainLinePressure) -- * 0.725) + -- Feed pressure to door line + self.DoorLinePressure = self.TrainToBrakeReducedPressure * 0.90 + local trainLineConsumption_dPdT = 0.0 + local wagc = Train.CarCount and Train:GetBLConnectedWagonCount() or #Train.WagonList + local HaveEPK = not Train.SubwayTrain or not Train.SubwayTrain.ARS or not Train.SubwayTrain.ARS.NoEPK + + local pr_speed = 1 + -- работа срывного клапана + if Train.AutostopValve.Value > 0 then + self:TriggerInput("Autostop",self.BrakeLinePressure > 1.86 and 1 or 2) --value == 2 — просто открыть срывной клапан без размыкания контактов УАВА + end + + if self.ValveType == 1 then + self.BLDisconnect = Train.DriverValveBLDisconnect.Value > 0 + self.TLDisconnect = Train.DriverValveTLDisconnect.Value > 0 and self.RealDriverValvePosition ~= 3 + pr_speed = 1*wagc--*((self.BrakeLinePressure-self.ReservoirPressure)/0.6) + if self.TLDisconnect then self.TLDisconnectPressure = self.TrainLinePressure end + if self.Leak or self.BrakeLineOpen then pr_speed = pr_speed*0.3 end + -- 334: 1 Fill reservoir from train line, fill brake line from train line + if (self.RealDriverValvePosition == 1) then + if self.TLDisconnect or self.ReservoirPressure ~= self.TLDisconnectPressure then + if self.BLDisconnect then + self.ReservoirPressure = self.BrakeLinePressure + self:equalizePressure(dT,"BrakeLinePressure", self.TLDisconnectPressure, pr_speed*(pr_speed < wagc and 1 or 1.35),nil,nil,2)--0.7 + else + self:equalizePressure(dT,"ReservoirPressure", self.TLDisconnectPressure, 3.55,nil,nil,2) + end + end + end + + -- 334: 2 Brake line, reservoir replenished from brake line reductor + if (self.RealDriverValvePosition == 2) then + if self.TLDisconnect then + local a = 1 + if self.EmergencyValve or Train.EmergencyBrakeValve.Value > 0.5 then a = 1.85 end + if self.BLDisconnect then + self.ReservoirPressure = self.BrakeLinePressure + self:equalizePressure(dT,"BrakeLinePressure", self.TrainToBrakeReducedPressure, pr_speed*0, pr_speed*0.6*a, nil, 1.6) + self.ReservoirPressure_dPdT = self.BrakeLinePressure_dPdT*0.8 + else + self:equalizePressure(dT,"ReservoirPressure", self.TrainToBrakeReducedPressure,0,1.55,nil,2) + end + end + end + + -- 334: 3 Close all valves + if (self.RealDriverValvePosition == 3) then + -- Typical leak + self:equalizePressure(dT,"ReservoirPressure", 0.00, 0.001) + end + + local res_dischrg_rate4 = self.BLDisconnect and 0.55 or 8 + local res_dischrg_rate5 = self.BLDisconnect and 1.12 or 8 + -- 334: 4 Reservoir open to atmosphere, brake line equalizes with reservoir + if (self.RealDriverValvePosition == 4) then + self:equalizePressure(dT,"ReservoirPressure", 0.0, res_dischrg_rate4, nil,nil,6)--0.35)-0.55 + end + + -- 334: 5 Reservoir and brake line open to atmosphere + if (self.RealDriverValvePosition == 5) then + self:equalizePressure(dT,"ReservoirPressure", 0.0, res_dischrg_rate5)--,nil,nil,2)--1.70 + local pr_speed = 1.25*wagc + if self.Leak or self.BrakeLineOpen then pr_speed = pr_speed*0.3 end + if self.BLDisconnect then + if self.Leak then pr_speed = pr_speed*6.2 end + self:equalizePressure(dT,"BrakeLinePressure", 0.0, pr_speed,nil,nil,2) + end + end + -- утечка через неплотность уравнительного поршня + if self.BLDisconnect then self:equalizePressure(dT, "ReservoirPressure", self.BrakeLinePressure, 0.06, 0) end + if (self.RealDriverValvePosition > 2) and (self.RealDriverValvePosition < 5) then + local pr_speed = 1.25*wagc + if self.Leak or self.BrakeLineOpen then pr_speed = pr_speed*0.3 end + local _a = 0 + for _i = 1, #Train.WagonList do + if Train.WagonList[_i].Pneumatic.TLDisconnect and Train.WagonList[_i].Pneumatic.BLDisconnect and (Train.WagonList[_i].Pneumatic.RealDriverValvePosition == 2 or Train.WagonList[_i].Pneumatic.RealDriverValvePosition == 1) then + _a = _a + 1 + end + if _a > 0 then break end + end + if _a > 0 then pr_speed = pr_speed*0.1 end + if self.BLDisconnect and self.BrakeLinePressure - self.ReservoirPressure > (self.RealDriverValvePosition == 3 and 0 or self.RealDriverValvePosition == 4 and 0.2 or 100) then --0.2 bar is a piston sensitivity + self:equalizePressure(dT, "BrakeLinePressure", 0, pr_speed*math.abs(self.BrakeLinePressure - self.ReservoirPressure), nil, nil, 6) + end + end + + if not self.TLDisconnect then + self.TLDisconnectPressure = math.max(0,self.TLDisconnectPressure - math.abs(self.ReservoirPressure_dPdT)*dT) + end + self.ReservoirPressure_dPdT = self.ReservoirPressure_dPdT + self.BrakeLinePressure_dPdT*0.2 + Train:SetPackedRatio("ReservoirPressure_dPdT",self.ReservoirPressure_dPdT/wagc*2) + --[[ + ---------------debug--------------------- + self.dlreadtimer = self.dlreadtimer or CurTime() + if CurTime() - self.dlreadtimer > 1.0 then + self.dlreadtimer = CurTime() + if Train:GetDriver() then + PrintMessage(HUD_PRINTTALK, Format("Вагон %u; P ТМ: %.3f; P УР =%.3f; Утечка ТМ %.3f; TLDis = %.3f; pr_speed = %.3f",Train:GetWagonNumber(),self.BrakeLinePressure,self.ReservoirPressure,self.BrakeLinePressure_dPdT, self.TLDisconnectPressure, pr_speed)) + end + end + ---------------debug---------------------]] + trainLineConsumption_dPdT = trainLineConsumption_dPdT + math.max(0,self.BrakeLinePressure_dPdT) + trainLineConsumption_dPdT = trainLineConsumption_dPdT + math.max(0,self.ReservoirPressure_dPdT)*0.05 + else + pr_speed = 2.8--1.25*wagc --2 + local pz_speed + -- wagc | pr_speed + ------------------ + -- 1 | 8.455 + -- 2 | 7.865 + -- 3 | 7.376 + -- 4 | 6.969 + -- 5 | 6.627 + -- 6 | 6.341 + -- 7 | 6.100 + -- 8 | 5.900 + --pr_speed = (0.4*math.exp(0.1*wagc-1)+1)*160/(2*wagc+20) --2 + --[[ + ---------------debug--------------------- + self.brreadtimer = self.brreadtimer or CurTime() + if CurTime() - self.brreadtimer > 1.0 then + self.brreadtimer = CurTime() + if Train:GetDriver() and Train.R_Radio.Value > 0 then + --PrintMessage(HUD_PRINTTALK, Format("br_threshold = %.3f; WcBl = %s",br_threshold, tostring(WcBl))) + --PrintMessage(HUD_PRINTTALK, Format("Это %s", isLVZ and "ЛВЗ" or "не ЛВЗ")) + --PrintMessage(HUD_PRINTTALK, Format("Вагон %u; Авторежим: %.3f",Train:GetWagonNumber(),self.WeightLoadRatio)) + --PrintMessage(HUD_PRINTTALK, Format("wagc = %u",wagc)) + end + end + ---------------debug---------------------]] + --local frc = 0.4--0.35 + --if Train.EPK.Value > 0 or self.EmergencyValve or self.BrakeLineOpen then pz_speed = pr_speed*0.75 else pz_speed = pr_speed*1.3 end + if self.Leak or self.BrakeLineOpen then pz_speed = pr_speed*0.75 else pz_speed = pr_speed*1.3 end + self.BLDisconnect = self.DisconnectType and Train.DriverValveBLDisconnect.Value > 0 or Train.DriverValveDisconnect.Value > 0 + self.TLDisconnect = self.DisconnectType and Train.DriverValveTLDisconnect.Value > 0 or Train.DriverValveDisconnect.Value > 0 + if self.RealDriverValvePosition > 4 and not self.km13_error2 then self.km13_error2 = 0.7 end + -- 013: 1 Overcharge + if (self.RealDriverValvePosition == 1) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > self.TrainLinePressure) then + self:equalizePressure(dT,"BrakeLinePressure", math.min(6.4,self.TrainLinePressure), pr_speed, pz_speed, nil, 1.0) + end + + -- 013: 2 Normal pressure + if (self.RealDriverValvePosition == 2) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > 1.01*math.min(self.KM013offset,self.TrainToBrakeReducedPressure)) then--was pr_speed*2 + self:equalizePressure(dT,"BrakeLinePressure", 1.01*math.min(self.KM013offset+(self.km13_error2 or 0),self.TrainLinePressure), pr_speed, pz_speed, nil, 2.5)-- nil, 1.0) + if self.km13_error2 and self.BrakeLinePressure >= self.KM013offset+self.km13_error2-0.1 then + self:equalizePressure(dT,"BrakeLinePressure", 1.01*math.min(self.KM013offset,self.TrainToBrakeReducedPressure), 35, pz_speed, nil, 1) + self.km13_error2 = nil + end + end + + -- 013: 3 4.3 Atm + if (self.RealDriverValvePosition == 3) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > 1.01*math.min(4.3,self.TrainToBrakeReducedPressure)) then + self:equalizePressure(dT,"BrakeLinePressure", 1.01*math.min(4.3,self.TrainToBrakeReducedPressure), pr_speed,pz_speed, nil, 2.5) + end + + -- 013: 4 4.0 Atm + if (self.RealDriverValvePosition == 4) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > 1.01*math.min(4.0,self.TrainToBrakeReducedPressure)) then + self:equalizePressure(dT,"BrakeLinePressure", 1.01*math.min(4.0,self.TrainToBrakeReducedPressure), pr_speed,pz_speed, nil, 2.5) + end + + -- 013: 5 3.7 Atm + if (self.RealDriverValvePosition == 5) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > 1.01*math.min(3.7,self.TrainToBrakeReducedPressure)) then + self:equalizePressure(dT,"BrakeLinePressure", 1.01*math.min(3.7,self.TrainToBrakeReducedPressure), pr_speed,pz_speed, nil, 2.5) + end + + -- 013: 6 3.0 Atm + if (self.RealDriverValvePosition == 6) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > 1.01*math.min(3.0,self.TrainToBrakeReducedPressure)) then + self:equalizePressure(dT,"BrakeLinePressure", 1.01*math.min(3.0,self.TrainToBrakeReducedPressure), pr_speed,pz_speed, nil, 2.5) + end + + -- 013: 7 0.0 Atm + if (self.RealDriverValvePosition == 7) and self.BLDisconnect and (self.TLDisconnect or self.BrakeLinePressure > 0.0) then + self:equalizePressure(dT,"BrakeLinePressure", 0.0, (0.6 + pr_speed*math.exp(math.min(0,self.BrakeLinePressure - 2.3)*1.0))*(0.15*wagc+1),pz_speed, nil, 2.5) + end + trainLineConsumption_dPdT = trainLineConsumption_dPdT + math.max(0,self.BrakeLinePressure_dPdT) + end + local leak + self.Leak = false + if wagc ~= Train.OldWagIsoCount or not Train.pr_spd_init then + pr_speed = (0.4*math.exp(0.1*wagc-1)+1)*160/(2*wagc+20) --2 + Train.OldWagIsoCount = wagc + Train.pr_spd_init = true + end + if HaveEPK and Train.EPKC then + local leak = 0 + local epkDiff = math.abs(self.EPKPressure-self.BrakeLinePressure) + if self.BLDisconnect and Train.EPK.Value>0 then + if Train.EPKC.Value>0 then + self:equalizePressure(dT,"EPKPressure", self.BrakeLinePressure,math.min(1,epkDiff)*6, math.min(1,epkDiff)*16,false,4*epkDiff*2) + end + if self.EPKPressure0.3 then + leak = self:equalizePressure(dT,"BrakeLinePressure", self.EPKPressure,pr_speed*epkDiff/3.8,pr_speed*epkDiff/3.28) + end + self.Leak = self.Leak or leak<-0.1 + end + if Train.EPK.Value == 0 or Train.EPKC.Value == 0 then + leak = leak+self:equalizePressure(dT,"EPKPressure", 0,16,false,false,5) + end + if self.ValveType==2 and not self.BLDisconnect then + self:equalizePressure(dT,"EPKPressure", 0,16,false,false,5) + end + Train:SetPackedRatio("EmergencyValveEPK_dPdT", -leak/wagc*8) + end + if self.ValveType == 1 then + Train:SetPackedRatio("Crane_dPdT", self.ReservoirPressure_dPdT ) + else + Train:SetPackedRatio("Crane_dPdT", self.BrakeLinePressure_dPdT/wagc*3 ) + end + if self.EmergencyValveDisable then + self.EmergencyValveDisable=false + self.EmergencyValve=false + Train.AutoStopNotify=false + end + local leak = 0 + if self.EmergencyValve then + local leakst = self.BLDisconnect and math.max(0.3,math.log(self.BrakeLinePressure,1.2) - 2.0) or math.max(1.6,math.log(0.63*self.BrakeLinePressure,1.15)) + leak = self:equalizePressure(dT,"BrakeLinePressure", 0.0,leakst*wagc/6)--,false,false,10) + if Train.UAVA.Value > 0 or (self.BrakeLinePressure < 1.8 and Train.AutostopValve.Value == 0) then --пока держим ЛКМ нажатой, срывной клапан открыт + self.EmergencyValveDisable = true + end + self.Leak = true + end + + local UAVABlocked = (self.BrakeLinePressure>1.8 and Train.UAVA.Value==0) + if (Train.UAVA.Blocked>0) ~= UAVABlocked then + Train.UAVA:TriggerInput("Block",UAVABlocked and 1 or 0) + end + + local UAVACBlocked = self.EmergencyValve and not self.EmergencyValveDisable + if (Train.UAVAC.Blocked>0) ~= UAVACBlocked then + Train.UAVAC:TriggerInput("Block",UAVACBlocked and 1 or 0) + end + + Train:SetPackedRatio("EmergencyValve_dPdT", -0.6*leak/wagc) --Регулировка свиста срывного клапана was -1.8 + + local leak = 0 + if Train.EmergencyBrakeValve and Train.EmergencyBrakeValve.Value > 0.5 then + local leakst = math.max(0.5,math.exp(0.5*self.BrakeLinePressure)) + leak = self:equalizePressure(dT,"BrakeLinePressure", 0.0,leakst)--,false,false,10) --was leakst*wagc/5 + self.Leak = true + end + Train:SetPackedRatio("EmergencyBrakeValve_dPdT", -leak/wagc) + ---------------------------------------------------------------------------- + -- Fill brake cylinders + if self.WCChargeValve == true then + self:equalizePressure(dT,"WorkingChamberPressure",self.BrakeLinePressure,0.094,nil,nil,1.0) --simulate 0.8mm hole btw BL and working chambers + end + local aird_ready = self.WorkingChamberPressure >= 2.2 + self.WCChargeValve = not ((self.WorkingChamberPressure - self.BrakeLinePressure) > 0.2 and (self.WorkingChamberPressure - self.BrakeLinePressure) < 2.5) + local KLSZ = self.WorkingChamberPressure > 5.2 and not self.WCChargeValve + if KLSZ then + self:equalizePressure(dT,"WorkingChamberPressure",0.0,0.12) -- КЛСЗ + end + + trainLineConsumption_dPdT = trainLineConsumption_dPdT + math.max(0,self.WorkingChamberPressure_dPdT*0.2) + self.GN2Offset = self.GN2Offset or math.random(20,100)*0.002 + (self.GN2Start or 2.5) + self.GN1Offset = self.GN1Offset or math.random(20,100)*0.002 + (self.GN1Start or 0.9) + self.BcBl = (self.GN2Offset + self.WeightLoadRatio*(self.GN2Offset - 1.4))/1.82--1.92 + if Train.AirDistributorDisconnect.Value == 0 and aird_ready then + -- Valve #1 + if (Train.PneumaticNo1.Value == 1.0) and (Train.PneumaticNo2.Value == 0.0) then + if self.PN1 < self.GN1Offset then + self.PN1 = math.min(self.TrainLinePressure,self.GN1Offset) + end + elseif Train.PneumaticNo1.Value == 0 and self.PN1 > 0.0 then + self.PN1 = self.BrakeCylinderPressure > 0.2 and 0.05 or self.PN1 - 0.5*dT + end + -- Valve #2 + if Train.PneumaticNo2.Value == 1.0 then + self.PN2 = math.min(self.TrainLinePressure,(self.GN2Offset + self.WeightLoadRatio*1.3)) + if self.BePN2 == false and self.BrakeCylinderPressure > 1.6 then + Train:PlayOnce("PN2end","stop") + end + self.BePN2 = true + elseif self.PN2 > 0.0 then + self.PN2 = self.BrakeCylinderPressure > 0.4 and 0.2 or self.PN2 - 0.5*dT + end + + self.BchExh = self.WorkingChamberPressure < 4.8 and self.BrakeLinePressure < 3.4 and 0 or 1 + self.cranPres = math.max(0,self.BcBl*(self.WorkingChamberPressure - self.BrakeLinePressure*self.BchExh)*(self.BrakeLinePressure > self.KM013offset and (0.6 + self.PN1*0.43) or 1)) + local targetPressure = math.max(0,math.min(self.GN2Offset + self.WeightLoadRatio*1.3, (self.cranPres < (self.PN1 + self.WeightLoadRatio*0.7) and (Train.PneumaticNo1.Value == 1.0) and (self.PN1 + self.WeightLoadRatio*0.7) or self.PN1) + self.PN2 + self.cranPres)) + if math.abs(self.BrakeCylinderPressure - targetPressure) > 0.150 then + self.BrakeCylinderValve = 1 + end + if math.abs(self.BrakeCylinderPressure - targetPressure) < 0.025 then + self.BrakeCylinderValve = 0 + end + if self.BrakeCylinderValve == 1 then + self:equalizePressure(dT,"BrakeCylinderPressure", math.min(self.GN2Offset + self.WeightLoadRatio*(self.GN2Offset - 1.4),targetPressure), 0.8, (Train.PneumaticNo1.Value > 0 or Train.PneumaticNo2.Value > 0) and 2.8 or 1.5, nil, 1.2) + end + trainLineConsumption_dPdT = trainLineConsumption_dPdT + math.max(0,self.BrakeCylinderPressure_dPdT*0.5) + elseif Train.AirDistributorDisconnect.Value ~= 0 then + self:equalizePressure(dT,"BrakeCylinderPressure", 0.0, 2.00) + end + if (self.BrakeCylinderPressure > 0.2 and self.BrakeCylinderPressure_dPdT > 0.1 or self.BrakeCylinderPressure_dPdT > 1) and not self.BrakeEngaged then + self.BrakeEngaged = true + Train:PlayOnce("brake","bass",1,math.Clamp(self.BrakeCylinderPressure_dPdT,0.7,1.2)) + end + if self.BrakeCylinderPressure < 1 and self.BrakeCylinderPressure_dPdT < -0.1 and self.BrakeEngaged then + self.BrakeEngaged = false + end + Train:SetPackedRatio("BrakeCylinderPressure_dPdT", self.BrakeCylinderPressure_dPdT) + self.TrainLinePressure = self.TrainLinePressure-math.max(0,self.BrakeCylinderPressure_dPdT*0.002) + if Train.PneumaticNo2.Value == 0 then + if self.BePN2 == true then + self.BePN2 = CurTime() + elseif self.BePN2 and self.BrakeCylinderPressure_dPdT > -0.2 then + Train:PlayOnce("PN2end","bass",math.Clamp(math.min(1,(CurTime()-self.BePN2)/1.3)*((3.2-self.BrakeCylinderPressure)/1.2),0,1)) + self.BePN2 = false + end + end + if self.BePN2 == false and (self.BrakeCylinderPressure_dPdT >= 0.2) then + self.BePN2 = nil + Train:PlayOnce("PN2end","stop") + end + + if Train.UAVAContact.Value > 0.5 and Train.UAVAC.Value < 0.5 then + Train.UAVAC:TriggerInput("Set",1) + Train:PlayOnce("uava_reset","bass",1) + end + + --Parking brake simulation + local PBPressure = math.Clamp(self.TrainLinePressure/5,0,1)*2.7 + if Train.ParkingBrake.Value == 0 then + self:equalizePressure(dT,"ParkingBrakePressure", PBPressure, 10,10,nil,0.5) + else + self:equalizePressure(dT,"ParkingBrakePressure", 0, 3,10,nil,0.5) + end + Train:SetPackedRatio("ParkingBrakePressure_dPdT",self.ParkingBrakePressure_dPdT) + trainLineConsumption_dPdT = trainLineConsumption_dPdT + math.max(0,self.ParkingBrakePressure_dPdT*0.5) + + -- Simulate cross-feed between different wagons + self:UpdatePressures(Train,dT) + + ---------------------------------------------------------------------------- + -- Simulate compressor operation and train line depletion + self.Compressor = Train.KK.Value * (Train.Electric.Aux750V > 550 and 1 or 0) + self.TrainLinePressure = self.TrainLinePressure - (Train.AirConsumeRatio or 0.06)*trainLineConsumption_dPdT*dT -- 0.190 --0.170 --0.07 + if self.Compressor == 1 then self:equalizePressure(dT,"TrainLinePressure", 10.0, Train.CompressorEfficiency or 0.07) end -- 0.04 + self:equalizePressure(dT,"TrainLinePressure", 0,Train.AirLeakRatio or 0.003) + -- Overpressure + if self.TrainLinePressure > math.max(7.2, (9.2 - self.TrainLineOverpressureValve*0.2)) and self.TrainLineOverpressureValve%2 == 0 then self.TrainLineOverpressureValve = self.TrainLineOverpressureValve + 1 end + if self.TrainLineOverpressureValve%2 == 1 then + self:equalizePressure(dT,"TrainLinePressure", 0.0, 0.2) + self.TrainLineOpen = true + if self.TrainLinePressure < 5.2 and self.TrainLineOverpressureValve < 20 then self.TrainLineOverpressureValve = self.TrainLineOverpressureValve + 1 end + end + + ---------------------------------------------------------------------------- + -- Pressure triggered relays + Train.AVT:TriggerInput("Open", self.BrakeCylinderPressure > 1.9) -- 1.8 - 2.0 + Train.AVT:TriggerInput("Close",self.BrakeCylinderPressure < 0.9) -- 0.9 - 1.5 + Train.AK:TriggerInput( "Open", self.TrainLinePressure > 8.2) + Train.AK:TriggerInput( "Close",self.TrainLinePressure < 6.3) + Train.AVU:TriggerInput("Open", self.BrakeLinePressure < 2.7) -- 2.7 - 2.9 + Train.AVU:TriggerInput("Close",self.BrakeLinePressure > 3.5) -- 3.5 - 3.7 + Train.SOT:TriggerInput("Open", self.EPKPressure < 1.3) -- 2.7 - 2.9 + Train.SOT:TriggerInput("Close", self.EPKPressure > 1.5) -- 2.7 - 2.9 + Train.BPT:TriggerInput("Set", (IsValid(Train.FrontBogey) and Train.FrontBogey.BrakeCylinderPressure+(not Train.FrontBogey.DisableParking and Train.FrontBogey.ParkingBrakePressure or 0) or self.BrakeCylinderPressure)>0.3) + Train.DKPT:TriggerInput("Set", self.BrakeCylinderPressure > 0.3) -- 1.8 - 2.0 + Train.SQ3:TriggerInput("Set", Train.PassengerDoor and 0 or 1) + + ---------------------------------------------------------------------------- + -- Simulate doors opening, closing + if self.DoorLinePressure > 3.5 then + if (Train.VDOL.Value == 1.0) and (Train.VDOP.Value == 0.0) and not self.DoorLeft then + self.DoorLeft = true + if self.VDOLLoud then Train:PlayOnce("vdol_loud","cabin",0.8+math.random()*0.2,self.VDOLLoud) end + end + if (Train.VDOL.Value == 0.0) and (Train.VDOP.Value == 1.0) and not self.DoorRight then + self.DoorRight = true + if self.VDORLoud then Train:PlayOnce("vdop_loud","cabin",0.8+math.random()*0.2,self.VDORLoud) end + end + if (Train.VDZ.Value == 1.0 or Train.VDOL.Value == 1.0 and Train.VDOP.Value == 1.0 or self.RZDTimer) and (self.DoorLeft or self.DoorRight) then + if not self.OpenWaitL or CurTime()-self.OpenWaitL < 0.2 then + self.DoorLeft = false + end + if not self.OpenWaitR or CurTime()-self.OpenWaitR < 0.2 then + self.DoorRight = false + end + else + self.CloseValue = nil + end + if Train.VDOL.Value == 1.0 and Train.VDOP.Value == 1.0 then + self.RZDTimer = CurTime() + elseif self.RZDTimer and CurTime()-self.RZDTimer > 0.1 then + self.RZDTimer = nil + end + end + if self.VDOL ~= Train.VDOL.Value then + self.VDOL = Train.VDOL.Value + self:equalizePressure(dT,"TrainLinePressure", 0.0, 0.05) + end + if self.VDOP ~= Train.VDOP.Value then + self.VDOP = Train.VDOP.Value + self:equalizePressure(dT,"TrainLinePressure", 0.0, 0.05) + end + if self.VDZ ~= Train.VDZ.Value then + self.VDZ = Train.VDZ.Value + self:equalizePressure(dT,"TrainLinePressure", 0.0, 0.05) + end + + + Train.LeftDoorsOpen = false + Train.RightDoorsOpen = false + local openL = true + local openR = true + for i=1,4 do + self.LeftDoorDir[i] = math.Clamp(self.LeftDoorDir[i]+dT/(self.DoorLeft and self.LeftDoorSpeed[i] or -self.LeftDoorSpeed[i]),-1,1) + self.RightDoorDir[i] = math.Clamp(self.RightDoorDir[i]+dT/(self.DoorRight and self.RightDoorSpeed[i] or -self.RightDoorSpeed[i]),-1,1) + self.LeftDoorState[i] = math.Clamp(self.LeftDoorState[i] + ((self.LeftDoorDir[i]/self.LeftDoorSpeed[i])*dT),0,1) + if self.LeftDoorState[i] == 0 or self.LeftDoorState[i] == 1 then self.LeftDoorDir[i] = 0 end + self.RightDoorState[i] = math.Clamp(self.RightDoorState[i] + ((self.RightDoorDir[i]/self.RightDoorSpeed[i])*dT),0,1) + if self.RightDoorState[i] == 0 or self.RightDoorState[i] == 1 then self.RightDoorDir[i] = 0 end + if not Train.LeftDoorsOpen and self.LeftDoorState[i] > 0 then + Train.LeftDoorsOpen = true + end + if self.LeftDoorState[i] > self.LeftDoorSpeed[i]/20 then self.OpenWaitL = false end + if self.RightDoorState[i] > self.LeftDoorSpeed[i]/20 then self.OpenWaitR = false end + if self.LeftDoorState[i] > 0 then openL = false end + if self.RightDoorState[i] > 0 then openR = false end + if not Train.RightDoorsOpen and self.RightDoorState[i] > 0 then + Train.RightDoorsOpen = true + end + Train:SetPackedRatio("DoorL"..i,self.LeftDoorState[i]) + Train:SetPackedRatio("DoorR"..i,self.RightDoorState[i]) + end + if openL and not self.OpenWaitL then self.OpenWaitL = CurTime() end + if openR and not self.OpenWaitR then self.OpenWaitR = CurTime() end + Train:SetPackedBool("DoorL",self.DoorLeft) + Train:SetPackedBool("DoorR",self.DoorRight) + Train.BD:TriggerInput("Set",not Train.RightDoorsOpen and not Train.LeftDoorsOpen) + + ---------------------------------------------------------------------------- + if self.DriverValveDisconnectPrevious ~= Train.DriverValveDisconnect.Value then + self.DriverValveDisconnectPrevious = Train.DriverValveDisconnect.Value + if self.DriverValveDisconnectPrevious == 0 then + self.DVDOffTimer = CurTime() + Train:PlayOnce("pneumo_disconnect2","cabin",0.9) + else + self.DVDOffTimer = nil + Train:PlayOnce("pneumo_disconnect1","cabin",0.9) + end + end + --Написано в описании КМ013, что при закрытии разобщительного он снижает давление в ТМ на 0.7, значит так и сделаем! + --(и обработку случая, когда в обеих кабинах разобщительный открыт не забудем) + local km013_setpoint = {6.4, self.KM013offset, 4.3, 4.0, 3.7, 3.0, 0} + if self.DVDOffTimer then + if self.BrakeLinePressure - (km013_setpoint[self.RealDriverValvePosition]-0.7) > 0.02 and CurTime()-self.DVDOffTimer < wagc*5/8 then + --print "Снижение давления в ТМ..." + local pr_speed = 22--1.4*wagc --2 + self:equalizePressure(dT,"BrakeLinePressure", math.max(0,km013_setpoint[self.RealDriverValvePosition]-0.7), pr_speed) + else + --print("Снижение давления в ТМ завершено за "..(CurTime()-self.DVDOffTimer).." секунд") + self.DVDOffTimer = nil + end + end + + ---------------------------------------------------------------------------- + -- FIXME + Train:SetNW2Bool("FbI",Train.FrontBrakeLineIsolation.Value ~= 0) + Train:SetNW2Bool("RbI",Train.RearBrakeLineIsolation.Value ~= 0) + Train:SetNW2Bool("FtI",Train.FrontTrainLineIsolation.Value ~= 0) + Train:SetNW2Bool("RtI",Train.RearTrainLineIsolation.Value ~= 0) + Train:SetNW2Bool("AD",Train.AirDistributorDisconnect.Value == 0) + Train:SetNW2Bool("UAVAContacts",Train.UAVAC.Value ~= 0) + + local ValveType = self.ValveType > 1 + self.Timer = self.Timer or CurTime() + if ((CurTime() - self.Timer > 0.10) and (self.DriverValvePosition > self.RealDriverValvePosition)) then + self.Timer = CurTime() + if not ValveType then + if self.RealDriverValvePosition ~= 3 then + Train:PlayOnce("br_334",self.RealDriverValvePosition.."-"..(self.RealDriverValvePosition+1)) + end + else + Train:PlayOnce("br_013","cabin") + end + self.RealDriverValvePosition = self.RealDriverValvePosition + 1 + end + if ((CurTime() - self.Timer > 0.10) and (self.DriverValvePosition < self.RealDriverValvePosition)) then + self.Timer = CurTime() + if not ValveType then + if self.RealDriverValvePosition ~= 5 then + Train:PlayOnce("br_334",self.RealDriverValvePosition.."-"..(self.RealDriverValvePosition-1)) + end + else + Train:PlayOnce("br_013","cabin") + end + self.RealDriverValvePosition = self.RealDriverValvePosition - 1 + end +end diff --git a/lua/metrostroi/systems/sys_pr_14x_panels.lua b/lua/metrostroi/systems/sys_pr_14x_panels.lua index c662442..5b87d85 100644 --- a/lua/metrostroi/systems/sys_pr_14x_panels.lua +++ b/lua/metrostroi/systems/sys_pr_14x_panels.lua @@ -31,7 +31,7 @@ function TRAIN_SYSTEM:Initialize() -- Реле-повторитель провода 8 (РП8) self.Train:LoadSystem("Rp8","Relay","REV-811T",{open_time = 0.2,bass = true }) -- Контактор дверей (КД) - self.Train:LoadSystem("KD","Relay","REV-811T",{ bass = true, close_time = 0.6 }) + self.Train:LoadSystem("KD","Relay","REV-811T",{ bass = true, close_time = 0.5 }) -- Реле остановки (РО) self.Train:LoadSystem("RO","Relay","KPD-110E",{ bass = true, close_time = 0--[[ , close_time = 0.1--]] }) end diff --git a/lua/metrostroi_data/languages/en_717.lua b/lua/metrostroi_data/languages/en_717.lua index cbcfbcb..bc80bcc 100644 --- a/lua/metrostroi_data/languages/en_717.lua +++ b/lua/metrostroi_data/languages/en_717.lua @@ -208,11 +208,11 @@ Common.717.AUTOSTOP = Engage emergency stop valve Common.717.HOD = Manually open Common.717.HCD = Manually close -Common.717.HDLK = Lock doors -Common.717.DoorReleaseExt = First door manual open valve -Common.717.DoorReleaseLeft = Emergency left doors manual open valve -Common.717.DoorReleaseRight = Emergency right doors manual open valve -Common.717.DVR87 = Door air distrubutor disconnect valve +Common.717.HDLK = Doors lock +Common.717.DoorReleaseExt = First right door emergency open valve +Common.717.DoorReleaseLeft = Left doors emergency open valve +Common.717.DoorReleaseRight = Right doors emergency open valve +Common.717.DVR87 = Doors air distrubutor disconnect valve #gmod_subway_81-717 Entities.gmod_subway_81-717_mvm.Buttons.Battery_C.1:UOSToggle = @[Common.ALL.UOS]