-------------------------------------------------------------------------------- -- ПУАВ - Поездное Устройство АвтоВедения -------------------------------------------------------------------------------- Metrostroi.DefineSystem("PUAV") TRAIN_SYSTEM.DontAccelerateSimulation = true function TRAIN_SYSTEM:Initialize() self.Train:LoadSystem("IPAV") self.Train:LoadSystem("KH","Relay","Switch",{ bass = true }) self.Train:LoadSystem("VAV","Relay","Switch",{ bass = true }) self.Train:LoadSystem("KSZD","Relay","Switch",{ bass = true }) self.Train:LoadSystem("VZP","Relay","Switch",{ bass = true }) self.Train:LoadSystem("VAU","Relay","Switch",{ bass = true, normally_closed = true }) self.Train:LoadSystem("RC2","Relay","Switch",{ bass = true, normally_closed = true }) self.Train:LoadSystem("P1","Relay","Switch",{ bass = true }) self.Train:LoadSystem("P2","Relay","Switch",{ bass = true }) self.Train:LoadSystem("P3","Relay","Switch",{ bass = true }) self.Train:LoadSystem("P4","Relay","Switch",{ bass = true }) self.Train:LoadSystem("P5","Relay","Switch",{ bass = true }) self.Selected = true self.LK16 = false self.LAVT = false self.LOS = false self.ARS = false self.LKI1 = false self.LKI2 = false self.LRSTimer = false self["2"] = 0 --Вращение РК self["3"] = 0 --Ход 3 self["8"] = 0 --Замещение электрического торможения self["16"] = 0 --Закрытие дверей self["17"] = 0 -- Разрешение восстановления реле перегрузки self["19"] = 0 -- Разрешение замещения электрического торможения self["20"] = 0 -- Включение двигателей self["20X"] = 0 -- Разрешение включения двигателей в ходовые режимы self["025"] = 0 -- Разрешение ручного торможения self["25"] = 0 -- Ручное торможение self["31"] = 0 --Разрешение открытия левых дверей self["31O"] = 0 --Открытие левых дверей self["32"] = 0 --Разрешение открытия правых дверей self["32O"] = 0 --Открытие правых дверей self["33"] = 0 --Включение ходового режима self["033"] = 0 --Разрешение включения ходового режима self["33G"] = 0 --Включение режима торможения self["39"] = 0 --Включение вентиля замещения № 2 self["48"] = 0 --Включение вентиля замещения № 1 self.KRH = 0 self.KRT = 0 self.KGR = 0 self.KRR1 = 0 self.KRR2 = 0 self.KRR3 = 0 self.KD = 0 self.KPRK = 0 self.KOAT = 0 self.KET = 0 self.KSOT = 0 self.KDL = 0 self.KDP = 0 self.RK1 = 0 self.KRU = 0 self.KVARS = 0 self.KTARS = 0 self.VAB = 0 self.KH3 = 0 self.VZP = 0 self.KSZD = 0 self.KB = 0 self.RD = 0 self.Ring = false self.State = -1 self.Stopped = false self.DoorsOpen = false self.Drive = 0 end if TURBOSTROI then return end function TRAIN_SYSTEM:Inputs() return { "IPAVCommand" } end function TRAIN_SYSTEM:Outputs() return { "31","32","31C","32C","16C"} end if CLIENT then local function createFont(name,font,size) surface.CreateFont("Metrostroi_"..name, { font = font, size = size, weight = 500, blursize = false, antialias = true, underline = false, italic = false, strikeout = false, symbol = false, rotary = false, shadow = false, additive = false, outline = false, extended = true, scanlines = false, }) end createFont("PUAV","Liquid Crystal Display",35,400) function TRAIN_SYSTEM:ClientThink() --RunConsoleCommand("say","президент!!!") if not self.DrawTimer then render.PushRenderTarget(self.Train.PUAV,0,0,512, 128) render.Clear(0, 0, 0, 0) render.PopRenderTarget() end if self.DrawTimer and CurTime()-self.DrawTimer < 0.1 then return end self.DrawTimer = CurTime() render.PushRenderTarget(self.Train.PUAV,0,0,512, 128) --render.Clear(0, 0, 0, 0) cam.Start2D() self:PUAVScreen(self.Train) cam.End2D() render.PopRenderTarget() end function TRAIN_SYSTEM:PrintText(x,y,text,inverse) local str = {utf8.codepoint(text,1,-1)} for i=1,#str do local char = utf8.char(str[i]) if inverse then draw.SimpleText(string.char(0x7f),"Metrostroi_PUAV",(x+i)*27+15,y*50+30,Color(0,0,0),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) draw.SimpleText(char,"Metrostroi_PUAV",(x+i)*27+15,y*50+30,Color(140,190,0,150),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) else draw.SimpleText(char,"Metrostroi_PUAV",(x+i)*27+15,y*50+30,Color(0,0,0),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) end end end function TRAIN_SYSTEM:PUAVScreen(Train) local State = Train:GetNW2Int("PUAV:State",-1) if State ~= 0 then surface.SetDrawColor(140*0.7,190*0.7,0,self.Warm and 130 or 255) self.Warm = true else surface.SetDrawColor(20,50,0,230) self.Warm = false end surface.DrawRect(0,0,512,128) if State == 0 then return end for i=1,6 do self:PrintText(-2+i*2,0,Format("%02d",i)) self:PrintText(-2+i*2,1,Format("%02d",math.max(0,Train:GetNW2Int("PUAV:RK"..i,0)))) end --self:PrintText(0,0,"010101010101") --self:PrintText(1,1,Format("РК:%02d",Train:GetNW2Int("PUAV:RK",0))) --self:PrintText(1,1,"(точнее криво)") end end function TRAIN_SYSTEM:Trigger(name,nosnd) end function TRAIN_SYSTEM:SetAVPosition(pos) if self.Train.KV.AutodrivePosition ~= pos then self.Train.KV:TriggerInput("SetAutodrive",pos) end end local IgnoreDoors = false function TRAIN_SYSTEM:Think(dT) if not self.Selected then return end local Train = self.Train local ALS = Train.ALSCoil local ARS = Train.ALS_ARS local EnableARS = ARS.EnableARS local UOS = not EnableARS and Train.RC1.Value == 0 local LeftCoil,RightCoil = Train.LeftAutoCoil,Train.RightAutoCoil local power = Train.VB.Value > 0.5 and Train.VAU.Value > 0.5 and Train.Panel["V1"] > 0.5 local KRUEnabled = Train.KRU and Train.KRU["14/1-B3"] > 0 local RVForward = power and (Train.KV["D4-15"] > 0 or KRUEnabled) local KVT = Train.PB.Value > 0 or Train.KVT and Train.KVT.Value > 0 local speed = math.Round(ALS.Speed or 0,1) if not power and self.State > -1 then self.State = -1 self.State2Timer = nil end if not RVForward and self.State > 0 then self.State = 0 end if RVForward and self.State == 0 then self.State = 2 end if RVForward and self.State == -1 and not self.State2Timer then self.State = 1 self.State2Timer = CurTime() end if RVForward and self.State == 1 and self.State2Timer and CurTime()-self.State2Timer > 2 then self.State = 2 self.State2Timer = nil end if self.State > 0 then self.NoFreq = ALS.NoFreq self.F1 = ALS.F1*(1-self.NoFreq) self.F2 = ALS.F2*(1-self.NoFreq) self.F3 = ALS.F3*(1-self.NoFreq) self.F4 = ALS.F4*(1-self.NoFreq) self.F5 = ALS.F5*(1-self.NoFreq) self.F6 = ALS.F6*(1-self.NoFreq) self.RealF5 = self.F5*(1-(self.F4+self.F3+self.F2+self.F1)) self.NoFreq = self.NoFreq + (1-math.min(1,self.F5+self.F4+self.F3+self.F2+self.F1)) else self.NoFreq = 0 self.F1 = 0 self.F2 = 0 self.F3 = 0 self.F4 = 0 self.F5 = 0 self.F6 = 0 self.NoFreq = 0 end if self.State == 2 then --Speed limit local speedLimit = 20 if EnableARS and self.F4 > 0 then speedLimit = 40 end if EnableARS and self.F3 > 0 then speedLimit = 60 end if EnableARS and self.F2 > 0 then speedLimit = 70 end if EnableARS and self.F1 > 0 then speedLimit = 80 end local ProgrammX = false local ProgramDoorLeft = IgnoreDoors local ProgramDoorRight = IgnoreDoors local ProgrammSBrake = false self.LastBrakeProgramTimer = self.LastBrakeProgramTimer or CurTime() self.LastBrakeProgram = self.LastBrakeProgram or false local haveCommand = 0 for k,v in ipairs(LeftCoil.Commands) do v.Power = true local command = v.PlateType ProgramDoorLeft = ProgramDoorLeft or command == METROSTROI_ACOIL_DOOR ProgrammX = ProgrammX or command == METROSTROI_ACOIL_DRIVE and v.Power and v.Mode ProgrammSBrake = ProgrammSBrake or command == METROSTROI_ACOIL_SBRAKE and LeftCoil haveCommand = haveCommand + 1 end for k,v in ipairs(RightCoil.Commands) do v.Power = true local command = v.PlateType ProgramDoorRight = ProgramDoorRight or command == METROSTROI_ACOIL_DOOR ProgrammX = ProgrammX or command == METROSTROI_ACOIL_DRIVE and v.Power and v.Mode ProgrammSBrake = ProgrammSBrake or command == METROSTROI_ACOIL_SBRAKE and RightCoil haveCommand = haveCommand + 1 end if self.HaveCommand ~= haveCommand then self.LRSTimer = CurTime() self.HaveCommand = haveCommand end if self.DoorsOpen == true and (Train.Panel["SD"] <= 0 or Train:ReadTrainWire(16) > 0) then self.DoorsOpen = false end if Train.VAV.Value > 0 and self.Stopped then if Train.Panel["SD"] > 0 and not self.SDTimer then self.SDTimer = CurTime() end if Train.Panel["SD"] <= 0 and self.SDTimer then self.SDTimer = false self.Autodrive = false end if self.SDTimer and (self.SDTimer == true or CurTime()-self.SDTimer > 0.2) then self.SDTimer = true self.Autodrive = self.Autodrive or Train.VZP.Value > 0 end else self.Autodrive = false self.Stopped = false end if Train.VAV.Value > 0 and Train.Panel["SD"] <= 0 and not self.Stopped then self.Stopped = CurTime() end if Train.VAV.Value > 0 and Train.Panel["SD"] > 0 and (self.Stopped and self.Stopped ~= true and CurTime()-self.Stopped >= 2) then self.Stopped = true end if self.Stopped and (Train.VAV.Value == 0 or Train.Panel["SD"] > 0 and (self.Stopped ~= true and CurTime()-self.Stopped < 2)) then self.Stopped = false end if not self.Autodrive then self.Drive = 0 self.Brake = false end if ProgrammSBrake then if self.RingArmed == nil then self.RingArmed = CurTime() + math.max(1,math.min(4,5-speed/15)) end elseif not ProgrammSBrake and self.RingArmed ~= nil then self.RingArmed = nil end if self.RingArmed and CurTime()-self.RingArmed <= 0 and Train:ReadTrainWire(6) > 0 then self.RingArmed = false end if self.RingArmed and CurTime()-self.RingArmed > 4 then self.RingArmed = false end local position = 0 if self.Autodrive and ProgrammSBrake then if not self.Brake and ProgrammSBrake then self.Brake = 0 end if self.Brake then position = speed > 55 and -2 or -1 end local passed = ProgrammSBrake.BrakeProgrammPassed local passednow = CurTime()-ProgrammSBrake.LastBrakeProgrammPassed if self.Brake == 0 and passed < 1e9 then self.Brake = 1 end if self.Brake == 1 and (passed < METROSTROI_ABRAKE_DIST or (passednow > self.Passed*4 and passednow > METROSTROI_ABRAKE_DIST*4)) then self.Brake = 2 end if self.Brake == 2 and METROSTROI_ABRAKE_DIST*3 < passed and passed < 1e9 and speed<=25 then self.Brake = 3 end if self.Brake == 3 and passed < METROSTROI_ABRAKE_DIST then self.Brake = 4 end --if self.Brake == 2 and speed > 25 or self.Brake == 4 then position = -3 end if self.Brake == 2 and Train.RheostatController.Position < 12 or self.Brake == 4 then position = -3 end self.Passed = passed elseif self.Autodrive then --print(-1,Train,ProgrammSBrake) if self.Brake then position = -3 elseif ProgrammX and ProgrammX then --X3 if ProgrammX == 2 or ProgrammX == 4 then self.Drive = 3 end --X3 if ProgrammX == 1 or ProgrammX == 3 then self.Drive = 2 end --X2 if ProgrammX == 5 or ProgrammX == 6 then self.Drive = 0 end --0 if ProgrammX == 7 then self.Drive = -1 end --T1 if ProgrammX == 8 then self.Drive = -2 end --T1a end if self.Brake and (self.Brake <= 1 or speed < 0.1) then self.Brake = false self.Stopped = false if ProgramDoorLeft or ProgramDoorRight then self.DoorsOpen = true end end if position == 0 then position = self.Drive or 0 end end if position ~= 0 and not self.Starting then self.Starting = CurTime() end if position == 0 and self.Starting then self.Starting = false end if (position < -1 or position > 1) and self.Starting and CurTime()-self.Starting < 0.5 then position = math.Clamp(position,-1,1) end if ARS["33D"]*self["33D"] == 0 and position > 0 then position = 0 end --if Train.RheostatController.Position < 17.2 then print(Train.Electric.I13,Train.RheostatController.Position,speed,Train.Electric.ThyristorState,Train.Electric.ThyristorResistance,Train.ThyristorBU5_6.Value) end self:SetAVPosition(position) if ProgrammSBrake then ProgrammSBrake.BrakeProgrammPassed = 1e9 end local zero = (self.NoFreq*(Train.ALS.Value+Train.VRD.Value)) > 0 --PUAV ARS logic if not EnableARS then self.Ringing = true self.EBrake = true end if self.Ringing and KVT then self.Ringing = false end if self.EBrake and KVT then self.EBrake = false end if speed >= speedLimit and not ARS.ElectricBrake and not self.Pneumo then self.Ringing = true self.Pneumo = speed == speedLimit self.EBrake = speed > speedLimit end if (speed < speedLimit or ARS.ElectricBrake) and EnableARS then self.Pneumo = false self.EBrake = false end local CloseDoors = (not ProgramDoorLeft and not ProgramDoorRight and not zero) or speed > 0.2 or Train.VAV.Value > 0 and Train.KSZD.Value > 0 local DoorLeftWork = Train:ReadTrainWire(16) == 0 and (ProgramDoorLeft or zero) local DoorRightWork = Train:ReadTrainWire(16) == 0 and (ProgramDoorRight or zero) self.LK16 = Train:ReadTrainWire(16) > 0 self.LAVT = Train.VAV.Value > 0 self.LOS = UOS self.LRS = not ProgramDoorLeft and not ProgramDoorRight and EnableARS and Train.EK.Value > 0 and Train.EK1.Value > 0 and Train.SOT.Value > 0 and (not self.LRSTimer or CurTime()-self.LRSTimer > 0.2) self.LKI1 = false self.LKI2 = false self["31"] = DoorLeftWork and self.DoorsOpen and 1 or 0 self["32"] = DoorRightWork and self.DoorsOpen and 1 or 0 self["31C"] = DoorLeftWork and 1 or 0 self["32C"] = DoorRightWork and 1 or 0 self["16C"] = CloseDoors and 1 or 0 --local zbrake = speedLimit <= 20 and not KVT self["33D"] = (self.EBrake or zbrake) and 0 or 1 self["33G"] = (self.EBrake or zbrake) and 1 or 0 self["2"] = self["33G"] self["20"] = self["33G"] self["48"] = self.Pneumo and 1 or 0 self["8"] = self["33G"] if Train.KV["U2-25"] > 0 or KVT and speedLimit == 20 then self["8"] = -1 end if (Train.KV["7G-33Yu"] > 0 or Train.KSZD.Value > 0) and self.KSZDRing then self.KSZDRing = false end for i,train in ipairs(Train.WagonList) do if train.RheostatController then Train:SetNW2Int("PUAV:RK"..i,math.floor(train.RheostatController.Position+0.5)) end end self.Ring = (self.EBrake or self.Ringing) and CurTime()%2 > 1 or self.KSZDRing elseif self.State == 1 then self.LK16 = true self.LAVT = true self.LOS = true self.LRS = true self.LKI1 = true self.LKI2 = true self.Ring = CurTime()-self.State2Timer < 1 self.EBrake = true self.Ringing = true else self.LK16 = false self.LAVT = false self.LOS = false self.LRS = false self.LKI1 = false self.LKI2 = false self["31"] = 0 self["32"] = 0 self["31C"] = 1 self["32C"] = 1 self["16C"] = 0 self["33D"] = 1 self["33G"] = 0 self["2"] = 0 self["20"] = 0 self["48"] = 0 self["8"] = 0 self.LRSTimer = false self.HaveCommand = false self.Ring = false self.EBrake = true self.Ringing = true self.Pneumo = false self.RingArmed = nil self:SetAVPosition(0) end if EnableARS then if (ARS.F5 > 0 or ARS.F6 > 0) then if not self.ZeroTimer then self.ZeroTimer = CurTime()+30 self.ZeroTimerState = true end if self.ZeroTimerState and self.ZeroTimer and CurTime()-self.ZeroTimer > 7.5 and Train.ALSCoil.Speed < 0.25 then self.ZeroTimerState = false self.ZeroTimer = CurTime()+30 end elseif self.ZeroTimer ~= nil then self.ZeroTimer = nil end else self.ZeroTimer = nil end --[[ if self.Train.VZP.Value > 0.5 then Train.Autodrive:Enable() end if Train.VAV.Value < 0.5 then Train.Autodrive:Disable() end if self.Timer and CurTime() - self.Timer > 0 then self.Timer = nil self.Choose = 0 end --self.FirstStation = Metrostroi.EndStations[Train.Announcer.AnnMap][self.Line] and Metrostroi.EndStations[Train.Announcer.AnnMap][self.Line][self.ChoosedFStation or 1] or 0 --self.LastStation = Metrostroi.EndStations[Train.Announcer.AnnMap][self.Line] and Metrostroi.EndStations[Train.Announcer.AnnMap][self.Line][self.ChoosedLStation or 1] or 0 if self.State ~= self.RealState then self.RealState = self.State self.TimeOverride = true end self.Time = self.Time or CurTime() if (CurTime() - self.Time) > 0.1 or self.TimeOverride then self.TimeOverride = nil --print(1) self.Time = CurTime() Train:SetNW2Int("PUAV:Choose",self.Choose) Train:SetNW2Int("PUAV:LastStation",self.LastStation or 1) Train:SetNW2Int("PUAV:FirstStation",self.FirstStation or 1) Train:SetNW2Int("PUAV:Line",self.Line or 1) end self.RouteNumber = string.gsub(Train.RouteNumber or "","^(0+)","") self.Line = Train.UPO.Line self.FirstStation = tostring(Train.UPO.FirstStation or "") self.LastStation = tostring(Train.UPO.LastStation or "") local pathID if (Metrostroi.TrainPositions[self.Train] and Metrostroi.TrainPositions[self.Train][1]) then PathID = Metrostroi.TrainPositions[self.Train][1].path.id end Train:SetPackedBool("LKI",self.Train.Autodrive.Commands[PathID] and self.Train.Autodrive.Commands[PathID][self.Train.UPO.Station] ~= nil)]] end