diff --git a/lua/autorun/metrostroi.lua b/lua/autorun/metrostroi.lua index e364ec7..57d7f1b 100644 --- a/lua/autorun/metrostroi.lua +++ b/lua/autorun/metrostroi.lua @@ -215,8 +215,33 @@ function Metrostroi.AddANSPAnnouncer(name,soundtable,datatable) print("Metrostroi: Added \""..name.."\" ASNP announcer.") end -Metrostroi.AnnouncementsSarmatUPO = {} -Metrostroi.SarmatUPOSetup = {} +Metrostroi.AnnouncementsSarmatUPO = { + [0] = { + name = "Default", + tone = {"subway_announcers/sarmat_upo/tone.mp3",1} + } +} +Metrostroi.SarmatUPOSetup = {[0] = { + name = "Default", + { + LED = {16,16}, + Name = "Обкатка", + {100,"Обкатка","Obkatka"}, + {101,"Обкатка","Obkatka"} + }, + { + LED = {16,16}, + Name = "Перегонка", + {200,"Перегонка","Peregonka"}, + {201,"Перегонка","Peregonka"} + }, + { + LED = {16,16}, + Name = "В депо", + {300,"В депо","В депо"}, + {301,"В депо","В депо"} + }, +}} function Metrostroi.AddSarmatUPOAnnouncer(name,soundtable,datatable) if not soundtable or not datatable then return end for k,v in pairs(Metrostroi.AnnouncementsSarmatUPO) do diff --git a/lua/entities/gmod_subway_81-722/cl_init.lua b/lua/entities/gmod_subway_81-722/cl_init.lua index fa54317..94f4a03 100644 --- a/lua/entities/gmod_subway_81-722/cl_init.lua +++ b/lua/entities/gmod_subway_81-722/cl_init.lua @@ -273,7 +273,7 @@ ENT.ButtonMap["PPZ"] = { {ID = "SF7Toggle", x=0+15.15*6, y=40+167*0, w=15,h=45, tooltip="SF7:Двери(управление)"}, {ID = "SF8Toggle", x=0+15.15*7, y=40+167*0, w=15,h=45, tooltip="SF8:БАРС 1"}, {ID = "SF9Toggle", x=0+15.15*8, y=40+167*0, w=15,h=45, tooltip="SF9:БАРС 2"}, - {ID = "R_UPOToggle", x=0+15.15*9, y=40+167*0, w=15,h=45, tooltip="SF: УПО1"}, + {ID = "SF00Toggle", x=0+15.15*9, y=40+167*0, w=15,h=45, tooltip="SF00:"}, {ID = "SF01Toggle", x=0+15.15*10, y=40+167*0, w=15,h=45, tooltip="SF01:"}, {ID = "SF10Toggle", x=0+15.15*11, y=40+167*0, w=15,h=45, tooltip="SF10:БРПИ-М1"}, {ID = "SF11Toggle", x=0+15.15*12, y=40+167*0, w=15,h=45, tooltip="SF11:БРПИ-М2"}, @@ -1155,16 +1155,16 @@ ENT.ButtonMap["Vityaz"] = { } } -ENT.ButtonMap["Sarmat"] = { - pos = Vector(470.85,41.65,-6.2), - ang = Angle(0.2,-64,67), - width = 1024, - height = 640, - scale = 0.02*0.567, +ENT.ButtonMap["BMCIK"] = { + pos = Vector(470.892,41.545,-6.23), + ang = Angle(0.2,-64.12,67), + width = 1280, + height = 800, + scale = 0.0089, sensor = true, - system = "SarmatUPO", - hideseat=0.2, - hide=true, + system = "BMCIK", + hideseat = 0.2, + hide = true } for i=1,3 do @@ -1180,39 +1180,63 @@ ENT.ButtonMap["RouteNumberSet"] = { pos = Vector(477,42.6,-2.75), ang = Angle(0,-90,0), width = 30, - height = 10, + height = 20, scale = 0.085, buttons = { {ID = "RouteNumber1Set",x=0,y=0,w=10,h=10, tooltip="Первая цифра"}, {ID = "RouteNumber2Set",x=10,y=0,w=10,h=10, tooltip="Вторая цифра"}, {ID = "RouteNumber3Set",x=20,y=0,w=10,h=10, tooltip="Третья цифра"}, + {ID = "RouteNumber13",x=5,y=10,w=20,h=10, tooltip="Правая и левая кнопки\n(удерживать для настройки яркости)"}, } } -ENT.ButtonMap["RouteNumber"] = { - pos = Vector(485.4,32.6,-4.55), - ang = Angle(0,90+5,88), - width = (7*8)*3+1*8*2, - height = 14*8, - scale = 0.23/4/(14/16), +ENT.ButtonMap["TNM"] = { + pos = Vector(485.4,32.62,-4.9), + ang = Angle(0,95,88), + width = 203, + height = 115, + scale = 0.06, - hide=2, + hide=2 } -ENT.ButtonMap["LastStation"] = { - pos = Vector(473.8,-12.5,43.5), +ENT.ButtonMap["BMTS"] = { + pos = Vector(473.8,-11.85,45.2-0.5), ang = Angle(0,90,90), width = 512, - height = 64, - scale = 0.1, - - hide=2, + height = 80, + scale = 0.0975, + hide = 2 } -ENT.ButtonMap["Tickers"] = { - pos = Vector(-455.4,-11.1,52.8), +ENT.ButtonMap["BIT1"] = { + pos = Vector(-455.37,-10.92504,52.35969), ang = Angle(0,90,90), - width = 512, - height = 64, - scale = 0.094, - hideseat=1.5, + width = 1024, + height = 192, + scale = 0.026947, + hideseat = 1.5 +} +ENT.ButtonMap["BIT2"] = { + pos = Vector(1.55365,-10.92493,51.99417), + ang = Angle(0,90,97), + width = 1024, + height = 192, + scale = 0.026947, + hideseat = 1.5 +} +ENT.ButtonMap["BIT3"] = { + pos = Vector(-4.83291,10.92509,51.99417), + ang = Angle(0,-90,97), + width = 1024, + height = 192, + scale = 0.026947, + hideseat = 1.5 +} +ENT.ButtonMap["BIT4"] = { + pos = Vector(377.70719,16.66898,52.35969), + ang = Angle(0,-90,90), + width = 1024, + height = 192, + scale = 0.026947, + hideseat = 1.5 } ENT.ButtonMap["SarmatButtons"] = { pos = Vector(476.2,30.2,-6.4), @@ -1222,14 +1246,14 @@ ENT.ButtonMap["SarmatButtons"] = { scale = 0.0625, buttons = { - {ID = "SarmatUpSet",x=6,y=2,w=14,h=13, tooltip="САРМАТ: Вверх"}, - {ID = "SarmatDownSet",x=6,y=2+13*1,w=14,h=13, tooltip="САРМАТ: Вниз"}, - {ID = "SarmatEnterSet",x=6,y=2+13*2,w=14,h=13, tooltip="САРМАТ: Enter"}, - {ID = "SarmatEscSet",x=6,y=2+13*3,w=14,h=13, tooltip="САРМАТ: Esc"}, - {ID = "SarmatF1Set",x=6,y=2+13*4,w=14,h=13, tooltip="САРМАТ: F1"}, - {ID = "SarmatF2Set",x=6,y=2+13*5,w=14,h=13, tooltip="САРМАТ: F2"}, - {ID = "SarmatF3Set",x=6,y=2+13*6,w=14,h=13, tooltip="САРМАТ: F3"}, - {ID = "SarmatF4Set",x=6,y=2+13*7,w=14,h=13, tooltip="САРМАТ: F4"}, + {ID = "SarmatUpSet",x=6,y=2,w=14,h=13, tooltip="БМЦИК: Вверх"}, + {ID = "SarmatDownSet",x=6,y=2+13*1,w=14,h=13, tooltip="БМЦИК: Вниз"}, + {ID = "SarmatEnterSet",x=6,y=2+13*2,w=14,h=13, tooltip="БМЦИК: Enter"}, + {ID = "SarmatEscSet",x=6,y=2+13*3,w=14,h=13, tooltip="БМЦИК: Esc"}, + {ID = "SarmatF1Set",x=6,y=2+13*4,w=14,h=13, tooltip="БМЦИК: F1"}, + {ID = "SarmatF2Set",x=6,y=2+13*5,w=14,h=13, tooltip="БМЦИК: F2"}, + {ID = "SarmatF3Set",x=6,y=2+13*6,w=14,h=13, tooltip="БМЦИК: F3"}, + {ID = "SarmatF4Set",x=6,y=2+13*7,w=14,h=13, tooltip="БМЦИК: F4"}, } } ENT.ButtonMap["BMP"] = { @@ -1240,10 +1264,21 @@ ENT.ButtonMap["BMP"] = { scale = 0.0625, buttons = { - {ID = "SarmatPathSet",x=6,y=4,w=13,h=14, tooltip="САРМАТ: Путь"}, - {ID = "SarmatLineSet",x=6,y=18,w=13,h=14, tooltip="САРМАТ: Линия"}, - {ID = "SarmatZeroSet",x=19,y=4,w=13,h=14, tooltip="САРМАТ: >0<"}, - {ID = "SarmatStartSet",x=19,y=18,w=13,h=14, tooltip="САРМАТ: Пуск"}, + {ID = "SarmatPathSet",x=6,y=4,w=13,h=14, tooltip="БМЦИК: Путь"}, + {ID = "SarmatLineSet",x=6,y=18,w=13,h=14, tooltip="БМЦИК: Линия"}, + {ID = "!SarmatLineLamp",x=7, y=19.5, radius=4, tooltip="БМЦИК: Светодиод Линия", model = { + lamp = { + speed=16, + model = "models/metrostroi_train/81-502/lamps/svetodiod_small_502.mdl", + var="BMCIK:LineEnabled", + z=-1.5, + color=Color(255,0,0), + scale = 0.5 + }, + sprite = {bright=0.2,size=0.15,scale=0.02,vscale=0.02,color=Color(255,0,0),z=0} + }}, + {ID = "SarmatZeroSet",x=19,y=4,w=13,h=14, tooltip="БМЦИК: >0<"}, + {ID = "SarmatStartSet",x=19,y=18,w=13,h=14, tooltip="БМЦИК: Пуск"}, } } ENT.Lights = { @@ -1280,12 +1315,11 @@ ENT.Lights = { } function ENT:Initialize() self.BaseClass.Initialize(self) - self.Vityaz = self:CreateRT("721Vityaz",1024,1024) - self.PAM = self:CreateRT("717PAM",1024,512) - self.Tickers = self:CreateRT("721Tickers",1024,128) - self.Sarmat = self:CreateRT("721Sarmat",1024,1024) - self.RouteNumber = self:CreateRT("721RouteNumber",256,128) - self.LastStation = self:CreateRT("721LastStation",512,64) + self.Vityaz = self:CreateRT("722MFDU",1024,1024) + self.BITScr = self:CreateRT("722BIT",1024,256) + self.BMCIKScr = self:CreateRT("722BMCIK",2048,1024) + self.TNMScr = self:CreateRT("722TNM",256,128) + self.BMTSScr = self:CreateRT("722BMTS",512,128) self.ReleasedPdT = 0 self.CraneRamp = 0 self.CraneRRamp = 0 @@ -1300,8 +1334,6 @@ function ENT:Initialize() self.CompressorVol = 0 self.ParkingBrake = 0 self.BrakeCylinder = 0.5 - self.BPSNBuzzVolume = 0 - end function ENT:UpdateWagonNumber() local count = math.max(4,math.ceil(math.log10(self.WagonNumber+1))) @@ -1328,17 +1360,22 @@ local Cpos = { local conPos = { 0,0.22,0.41,0.6,0.8,1 } +local function getBitValue(value, offset, bitCount) + local mask = bit.lshift(bit.lshift(1,bitCount)-1,offset) + return bit.rshift(bit.band(value,mask),offset) +end function ENT:Think() self.BaseClass.Think(self) if not self.RenderClientEnts or self.CreatingCSEnts then return end + local sarmatInvert = self:GetNW2Bool("SarmatInvert") if not self.PassSchemesDone then local sarmat,sarmatr = self.ClientEnts.sarmat,self.ClientEnts.sarmatr local scheme = Metrostroi.Skins["722_schemes"] and Metrostroi.Skins["722_schemes"][self.Scheme] if IsValid(sarmat) and IsValid(sarmatr) and scheme then - if self:GetNW2Bool("SarmatInvert") then + if sarmatInvert then sarmat:SetSubMaterial(0,scheme[2]) sarmatr:SetSubMaterial(0,scheme[1]) else @@ -1353,41 +1390,53 @@ function ENT:Think() self.PassSchemesDone = false self.Scheme = self:GetNW2Int("Scheme",1) end - if self.InvertSchemes ~= self:GetNW2Bool("SarmatInvert",false) then + if self.InvertSchemes ~= sarmatInvert then self.PassSchemesDone=false - self.InvertSchemes = self:GetNW2Bool("SarmatInvert",false) + self.InvertSchemes = sarmatInvert end - local Headlight = self:GetPackedRatio("Headlight") - self:SetLightPower(1,Headlight>0,Headlight) - self:SetLightPower(31,Headlight>0,Headlight) - self:SetLightPower(32,Headlight>0,Headlight) - self:SetLightPower(2,self:GetPackedBool("RedLights")) - self:SetLightPower(33,self:GetPackedBool("RedLights")) - self:SetLightPower(34,self:GetPackedBool("RedLights")) + local headlight = self:GetPackedRatio("Headlight") + self:SetLightPower(1,headlight>0,headlight) + self:SetLightPower(31,headlight>0,headlight) + self:SetLightPower(32,headlight>0,headlight) if IsValid(self.GlowingLights[1]) then - if self:GetPackedRatio("Headlights") < 1 and self.GlowingLights[1]:GetFarZ() ~= 7000 then + if headlight < 1 and self.GlowingLights[1]:GetFarZ() ~= 7000 then self.GlowingLights[1]:SetFarZ(7000) end - if self:GetPackedRatio("Headlights") == 1 and self.GlowingLights[1]:GetFarZ() ~= 8192 then + if headlight== 1 and self.GlowingLights[1]:GetFarZ() ~= 8192 then self.GlowingLights[1]:SetFarZ(8192) end end + self:ShowHide("HeadLightsH",headlight==0.5) + self:ShowHide("HeadLights",headlight>0.5) + + local redlights = self:GetPackedBool("RedLights") + self:ShowHide("RedLights",redlights) + self:SetLightPower(2,redlights) + self:SetLightPower(33,redlights) + self:SetLightPower(34,redlights) + self:SetLightPower(3,self:GetPackedBool("SOSD")) + local cablight = self:GetPackedRatio("CabLights") + self:ShowHide("lamps_cab_e",cablight>0) + self:ShowHide("lamps_cab_f",cablight>0.3) self:SetLightPower(10,cablight>0,cablight) self:SetLightPower("lamps_cab_e",cablight>0,cablight) self:SetLightPower("lamps_cab_f",cablight>0.3,cablight) local passlight = self:GetPackedRatio("SalonLighting") + self:ShowHideSmooth("lamps_salon",passlight) self:SetLightPower(11,passlight>0,passlight) self:SetLightPower(12,passlight>0,passlight) self:SetLightPower(13,passlight>0,passlight) - self:SetLightPower(14,self:GetPackedBool("PanelLighting")) - self:SetLightPower(15,self:GetPackedBool("PanelLighting")) - self:SetLightPower(16,self:GetPackedBool("PanelLighting")) - self:SetLightPower(17,self:GetPackedBool("PanelLighting")) + local panelLightning = self:GetPackedBool("PanelLighting") + self:ShowHide("led",panelLightning) + self:SetLightPower(14,panelLightning) + self:SetLightPower(15,panelLightning) + self:SetLightPower(16,panelLightning) + self:SetLightPower(17,panelLightning) local BortLSD,BortPneumo,BortBV = self:GetPackedBool("BortLSD"),self:GetPackedBool("BortPneumo"),self:GetPackedBool("BortBV") self:ShowHide("bortlamp_lsd",BortLSD) @@ -1400,7 +1449,6 @@ function ENT:Think() self:SetLightPower(22,BortBV,1) self:SetLightPower(25,BortBV,1) - self:ShowHide("led",self:GetPackedBool("PanelLighting")) --ANIMS self:Animate("brake_line", self:GetPackedRatio("BLPressure"), 0.037, 0.795, 256,2) self:Animate("train_line", self:GetPackedRatio("TLPressure"), 0.037, 0.795, 4096,2) @@ -1422,69 +1470,74 @@ function ENT:Think() self:Animate("UAVA", self:GetPackedBool("UAVA") and 1 or 0, 0, 0.25, 6,false) self:Animate("EmergencyBrakeValve", self:GetPackedBool("EmergencyBrakeValve") and 1 or 0, 0, 0.3, 6,false) - self:ShowHide("HeadLights",self:GetPackedBool("Headlights2")) - self:ShowHide("HeadLightsH",self:GetPackedBool("Headlights1")) - self:ShowHide("RedLights",self:GetPackedBool("RedLights")) - - self:ShowHideSmooth("lamps_salon",self:GetPackedRatio("SalonLighting")) - - self:ShowHide("lamps_cab_e",cablight>0) - self:ShowHide("lamps_cab_f",cablight>0.3) - self:ShowHide("doorl_l",self:GetPackedBool("DoorAlarmL")) - self:ShowHide("doorl_r",self:GetPackedBool("DoorAlarmR")) + local doorAlarm = self:GetNW2Int("BNT:DoorAlarm") + self:SetSoundState("door_alarm",getBitValue(doorAlarm,0,1),1) + self:ShowHide("doorl_l",getBitValue(doorAlarm,1,1) > 0) + self:ShowHide("doorl_r",getBitValue(doorAlarm,2,1) > 0) + --Радио self:ShowHide("rvs",self:GetPackedBool("RadioRVS")) self:Animate("RearBrake", self:GetNW2Bool("RbI") and 0 or 1,0,1, 3, false) self:Animate("RearTrain", self:GetNW2Bool("RtI") and 1 or 0,0,1, 3, false) - local led_back = self:GetPackedBool("PassSchemesLEDO",false) - if self:GetPackedBool("SarmatInvert",false) then led_back = not led_back end - local sleft,sright = self:GetPackedBool("SarmatLeft"),self:GetPackedBool("SarmatRight") - for i=1,4 do - self:ShowHide("led_l_f"..i,not led_back and sleft) - self:ShowHide("led_l_b"..i,led_back and sleft) - self:ShowHide("led_r_f"..i,not led_back and sright) - self:ShowHide("led_r_b"..i,led_back and sright) + local bntL = self:GetNW2Int("BNT:Left") + local bntR = self:GetNW2Int("BNT:Right") + local bntPowerL = getBitValue(bntL,0,1) + local bntPowerR = getBitValue(bntR,0,1) + local initL,initR = getBitValue(bntL,1,1) > 0, getBitValue(bntR,1,1) > 0 + local currL,currR = getBitValue(bntL,9,6),getBitValue(bntR,9,6) + + local invL,invR = getBitValue(bntL,2,1) > 0, getBitValue(bntR,2,1) > 0 + if sarmatInvert then + invL = not invL + invR = not invR end - local scurr = self:GetNW2Int("PassSchemesLED") - local snext = self:GetNW2Int("PassSchemesLEDN") - local led = scurr - if snext ~= 0 and CurTime()%2 > 1 then led = led + snext end - if scurr < 0 then led = math.floor(CurTime()%16.5*2) end - if led_back then - if sleft then - for i=1,4 do if IsValid(self.ClientEnts["led_l_b"..i]) then self.ClientEnts["led_l_b"..i]:SetSkin(math.Clamp(led-((i-1)*8),0,8)) end end + + if initL then + local nextL = getBitValue(bntL,3,6) + if nextL == 0 then nextL = -1 end + if CurTime()%2>1 then + currL = currL + nextL end - if sright then - for i=1,4 do if IsValid(self.ClientEnts["led_r_b"..i]) then self.ClientEnts["led_r_b"..i]:SetSkin(math.Clamp(led-((i-1)*8),0,8)) end end + end + if initR then + local nextR = getBitValue(bntR,3,6) + if nextR == 0 then nextR = -1 end + if CurTime()%2>1 then + currR = currR + nextR + end + end + for i=1,4 do + self:ShowHide("led_l_f"..i,not invL) + self:ShowHide("led_l_b"..i,invL) + self:ShowHide("led_r_f"..i,not invR) + self:ShowHide("led_r_b"..i,invR) + + if IsValid(self.ClientEnts["led_l_f"..i]) then self.ClientEnts["led_l_f"..i]:SetSkin(math.Clamp(currL-((i-1)*8),0,8)) end + if IsValid(self.ClientEnts["led_l_b"..i]) then self.ClientEnts["led_l_b"..i]:SetSkin(math.Clamp(currL-((i-1)*8),0,8)) end + if IsValid(self.ClientEnts["led_r_f"..i]) then self.ClientEnts["led_r_f"..i]:SetSkin(math.Clamp(currR-((i-1)*8),0,8)) end + if IsValid(self.ClientEnts["led_r_b"..i]) then self.ClientEnts["led_r_b"..i]:SetSkin(math.Clamp(currR-((i-1)*8),0,8)) end + end + + local tnmState = self:GetNW2Int("TNM:State",0) + if tnmState > 0 then + local rn = self:GetNW2Int("TNM:Number",0) + local hide = tnmState==2 and CurTime()%1.2>0.3 or tnmState==1 + for i=1,3 do + self:ShowHide("route_number"..i,hide) + if IsValid(self.ClientEnts["route_number"..i]) then + local number = math.floor(rn/10^(3-i)) % 10 + self.ClientEnts["route_number"..i]:SetSkin(number) + end end else - if sleft then - for i=1,4 do if IsValid(self.ClientEnts["led_l_f"..i]) then self.ClientEnts["led_l_f"..i]:SetSkin(math.Clamp(led-((i-1)*8),0,8)) end end - end - if sright then - for i=1,4 do if IsValid(self.ClientEnts["led_r_f"..i]) then self.ClientEnts["led_r_f"..i]:SetSkin(math.Clamp(led-((i-1)*8),0,8)) end end + for i=1,3 do + self:ShowHide("route_number"..i,false) end end - local rnwork = self:GetNW2Bool("RouteNumberWork") - local rn = self:GetNW2Int("RouteNumberSet") - for i=1,3 do - self:ShowHide("route_number"..i,rnwork) - if rnwork and IsValid(self.ClientEnts["route_number"..i]) then - local number = math.floor(rn/10^(3-i)) % 10 - --local d1 = math.floor(num) % 10 - --local d2 = math.floor(num / 10) % 10 - --local d3 = math.floor(num / 100) % 10 - self.ClientEnts["route_number"..i]:SetSkin(number) - end - end - --self:Animate("brake_cylinder", 0/6, 0.016, 0.78, 2,false) - --self:Animate("brake_line", 0/16, 0.037, 0.795, 2,false) - --self:Animate("train_line", 0/16, 0.037, 0.795, 2,false) - -- local playL = false local playR = false local anim = 0--math.Round(CurTime()%5/5) @@ -1569,7 +1622,7 @@ function ENT:Think() self:SetSoundState("parking_brake",self.ParkingBrake,1.4) local dPdT = self:GetPackedRatio("BrakeCylinderPressure_dPdT") - self.ReleasedPdT = math.Clamp(self.ReleasedPdT + 2*(-self:GetPackedRatio("BrakeCylinderPressure_dPdT",0)-self.ReleasedPdT)*dT,0,1) + self.ReleasedPdT = math.Clamp(self.ReleasedPdT + 2*(-dPdT-self.ReleasedPdT)*dT,0,1) local release1 = math.Clamp(self.ReleasedPdT,0,1)^2 self:SetSoundState("release",release1,1) @@ -1601,7 +1654,6 @@ function ENT:Think() self.EmergencyBrakeValveRamp = math.Clamp(self.EmergencyBrakeValveRamp + (emergencyBrakeValve-self.EmergencyBrakeValveRamp)*dT*8,0,1) self:SetSoundState("valve_brake",self.EmergencyBrakeValveRamp,0.8+math.min(0.4,self.EmergencyBrakeValveRamp*0.8)) - local emergencyValve = self:GetPackedRatio("EmergencyValve_dPdT", 0)^0.4*1.2 self.EmergencyValveRamp = math.Clamp(self.EmergencyValveRamp + (emergencyValve-self.EmergencyValveRamp)*dT*16,0,1) self:SetSoundState("emer_brake",self.EmergencyValveRamp,1.0) @@ -1634,7 +1686,6 @@ function ENT:Think() self:SetSoundState("rolling_60",rollingi*rol60,1) self:SetSoundState("rolling_70",rollingi*rol70,1) - local rol10 = math.Clamp(speed/15,0,1)*(1-math.Clamp((speed-18)/35,0,1)) local rol10p = Lerp((speed-15)/14,0.6,0.78) local rol40 = math.Clamp((speed-18)/35,0,1)*(1-math.Clamp((speed-55)/40,0,1)) @@ -1665,41 +1716,55 @@ function ENT:Think() self:SetSoundState("chopper", tunstreet*self:GetPackedRatio("chopper"), 1) local work = self:GetPackedBool("AnnPlay") - local UPO = work and self:GetPackedBool("AnnPlayUPO") + local UPO = work and self.Announcer.AnnTable == "AnnouncementsUPO" + local noise = self:GetNW2Int("AnnouncerNoise") + + local volBMCIK = self:GetNW2Int("BMCIK:VolCab",0)/10 + local volBNT = self:GetNW2Int("BNT:Volumes",0) - local noise = self:GetNW2Int("AnnouncerNoise", -1) - local volume = self:GetNW2Float("UPOVolume",1) - local noisevolume = self:GetNW2Float("UPONoiseVolume",1) - local buzzvolume = volume - if self.Sounds["announcer1"] and IsValid(self.Sounds["announcer1"]) then buzzvolume = UPO and (1-(self.Sounds["announcer1"]:GetLevel())*math.Rand(0.9,3))*buzzvolume*2 or 0 end - if self.BPSNBuzzVolume > buzzvolume then - self.BPSNBuzzVolume = math.Clamp(self.BPSNBuzzVolume + 8*(buzzvolume-self.BPSNBuzzVolume)*dT,0.1,1) + local volSalon = 0 + local noisevolume = 0 + if UPO then + noisevolume = self:GetNW2Float("UPONoiseVolume",1) + volSalon = getBitValue(volBNT,4,4)/10*self:GetNW2Float("UPOVolume",1) else - self.BPSNBuzzVolume = math.Clamp(self.BPSNBuzzVolume + 0.4*(buzzvolume-self.BPSNBuzzVolume)*dT,0.1,1) + volSalon = getBitValue(volBNT,0,4)/10 end for k,v in ipairs(self.AnnouncerPositions) do - self:SetSoundState("announcer_noiseW"..k,UPO and noisevolume*volume*0.7 or 0,1) - for i=1,3 do - self:SetSoundState(Format("announcer_noise%d_%d",i,k),(UPO and i==noise) and volume*self.BPSNBuzzVolume*self:GetNW2Float("UPOBuzzVolume",1)*0.7 or 0,1) + local targetVol = 0 + if work then + if v[4] == 0x4C then -- [L]eft side + targetVol = v[3]*volSalon*bntPowerL + elseif v[4] == 0x52 then -- [R]ight side + targetVol = v[3]*volSalon*bntPowerR + elseif v[4] == 0x43 then -- [C]abin + targetVol = v[3]*volBMCIK + end end - if IsValid(self.Sounds["announcer"..k]) then self.Sounds["announcer"..k]:SetVolume(work and v[3]*(UPO and volume or 1) or 0) end + self:SetSoundState("announcer_noiseW"..k,targetVol*noisevolume,1) + for i=1,3 do + self:SetSoundState(Format("announcer_noise%d_%d",i,k),(UPO and i==noise) and targetVol*noisevolume or 0,1) + end + + if IsValid(self.Sounds["announcer"..k]) then self.Sounds["announcer"..k]:SetVolume(targetVol) end end end -function ENT:OnAnnouncer(volume) - local work = self:GetPackedBool("AnnPlay") - local UPO = work and self:GetPackedBool("AnnPlayUPO") +-- TODO: Вспомнить Глебу, зачем вообще эта функция реализована +-- В обновлении 2018 года её нет +-- function ENT:OnAnnouncer(volume) +-- local work = self:GetPackedBool("AnnPlay") +-- local UPO = work and self:GetPackedBool("AnnPlayUPO") - return work and volume*(UPO and self:GetNW2Float("UPOVolume",1) or 1) or 0 -end +-- return work and volume*(UPO and self:GetNW2Float("UPOVolume",1) or 1) or 0 +-- end function ENT:Draw() self.BaseClass.Draw(self) end -local CamRTM = Material( "pp/rt" ) function ENT:DrawPost() self.RTMaterial:SetTexture("$basetexture", self.Vityaz) self:DrawOnPanel("Vityaz",function(...) @@ -1707,39 +1772,28 @@ function ENT:DrawPost() surface.SetDrawColor(255,255,255) surface.DrawTexturedRectRotated(512,512,1024,1024,0) end) - --[[ self.RTMaterial:SetTexture("$basetexture", self.PAM) - self:DrawOnPanel("PAMScreen",function(...) + self.RTMaterial:SetTexture("$basetexture", self.BMCIKScr) + self:DrawOnPanel("BMCIK",function(...) surface.SetMaterial(self.RTMaterial) - surface.SetDrawColor(255,255,255) - surface.DrawTexturedRectRotated(512,256,1024,512,0) - end)--]] - self.RTMaterial:SetTexture("$basetexture", self.Sarmat) - self:DrawOnPanel("Sarmat",function(...) - surface.SetMaterial(self.RTMaterial) - surface.SetDrawColor(255,255,255) - surface.DrawTexturedRectRotated(512,512,1024,1024,0) - - --surface.SetMaterial(self.RTMaterial2) - --surface.SetDrawColor(255,255,255) - --self.RTMaterial2:SetTexture("$basetexture", self.SarmatUPO.Cam1) - --surface.DrawTexturedRectRotated(384,128,256,256,0) - --self.RTMaterial2:SetTexture("$basetexture", self.SarmatUPO.Cam2) - --surface.DrawTexturedRectRotated(128,128,256,256,0) + surface.SetDrawColor(255,255,255,255) + surface.DrawTexturedRectRotated(1024,512,2048,1024,0) end) - self.RTMaterial:SetTexture("$basetexture", self.LastStation) - self:DrawOnPanel("LastStation",function(...) - surface.SetMaterial(self.RTMaterial) + self.RTMaterial:SetTexture("$basetexture", self.BMTSScr) + self:DrawOnPanel("BMTS",function(...) surface.SetDrawColor(255,255,255) - surface.DrawTexturedRectRotated(256,32,512,64,0) - end) - self.RTMaterial:SetTexture("$basetexture", self.Tickers) - self:DrawOnPanel("Tickers",function(...) surface.SetMaterial(self.RTMaterial) - surface.SetDrawColor(255,255,255) - surface.DrawTexturedRectRotated(256,32,512,64,0) + surface.DrawTexturedRectRotated(256,64,512,128,0) end) - self.RTMaterial:SetTexture("$basetexture", self.RouteNumber) - self:DrawOnPanel("RouteNumber",function(...) + self.RTMaterial:SetTexture("$basetexture", self.BITScr) + surface.SetDrawColor(255,255,255,200) + for i=1,4 do + self:DrawOnPanel("BIT"..i,function(...) + surface.DrawTexturedRectRotated(512,128,1024,256,0) + end) + end + self.RTMaterial:SetTexture("$basetexture", self.TNMScr) + surface.SetDrawColor(255,255,255) + self:DrawOnPanel("TNM",function(...) surface.SetMaterial(self.RTMaterial) surface.SetDrawColor(255,255,255) surface.DrawTexturedRectRotated(128,64,256,128,0) @@ -1782,4 +1836,4 @@ for id,panel in pairs(ENT.ButtonMap) do end end end -Metrostroi.GenerateClientProps() +Metrostroi.GenerateClientProps() \ No newline at end of file diff --git a/lua/entities/gmod_subway_81-722/init.lua b/lua/entities/gmod_subway_81-722/init.lua index 10c7790..b28ec1d 100644 --- a/lua/entities/gmod_subway_81-722/init.lua +++ b/lua/entities/gmod_subway_81-722/init.lua @@ -4,7 +4,7 @@ include("shared.lua") ENT.BogeyDistance = 650 -- Needed for gm trainspawner ENT.SyncTable = { - "SF1","SF2","SF3","SF4","SF5","SF6","SF7","SF8","SF9","R_UPO","SF01","SF10","SF11","SF12","SF13","SF02", + "SF1","SF2","SF3","SF4","SF5","SF6","SF7","SF8","SF9","SF00","SF01","SF10","SF11","SF12","SF13","SF02", "SF14","SF15","SF16","SF17","SF18","SF19","SF20","SF21","SF22","SF23","SF24","SF25","SF26","SF27","SF03","SF04", "SF31","SF32","SF33","SF34","SF35","SF36","SF37","SF38","SF41","SF42","SF43","SF44","SF45","SF46","SF47","SF48","SF49","SF51","SF52","SF53","SF54","SF55","SF56","SF57","SF58","SF59", @@ -102,6 +102,8 @@ function ENT:Initialize() [KEY_7] = "PanelKV7", [KEY_8] = "EmergencyDriveSet", + [KEY_EQUAL] = "SarmatStartSet", + [KEY_0] = "KRO+", [KEY_9] = "KRO-", [KEY_V] = "DoorCloseA", @@ -109,20 +111,19 @@ function ENT:Initialize() [KEY_D] = "DoorRight", [KEY_SPACE] = "PBSet", [KEY_BACKSPACE] = {"EmergencyBrakeToggle",helper="EmergencyBrakeValveToggle"}, - [KEY_PAD_ENTER] = "KVWrenchKV", [KEY_LSHIFT] = { [KEY_2] = "RingSet", [KEY_S] = "PanelKV7", [KEY_V] = "DoorCloseM", [KEY_SPACE] = "VigilanceSet", - - [KEY_PAD_ENTER] = "KVWrenchNone", }, [KEY_LALT] = { [KEY_UP] = "SarmatUpSet", [KEY_DOWN] = "SarmatDownSet", [KEY_RIGHT] = "SarmatEnterSet", [KEY_LEFT] = "SarmatEscSet", + [KEY_PAD_ENTER] = "SarmatEnterSet", + [KEY_PAD_DECIMAL] = "SarmatEscSet", [KEY_PAD_1] = "SarmatF1Set", [KEY_PAD_2] = "SarmatF2Set", [KEY_PAD_3] = "SarmatF3Set", @@ -189,8 +190,8 @@ function ENT:Initialize() self.CabinDoorRight = false self.RearDoor = false - self:SetNW2Float("UPONoiseVolume",math.Rand(0,0.3)) - self:SetNW2Float("UPOVolume",math.Rand(0.8,1)) + self.UPONoiseVolume = math.Rand(0,0.3) + self.UPOVolume = math.Rand(0.8,1) self.Scheme = 1 end @@ -205,7 +206,7 @@ function ENT:NonSupportTrigger() end function ENT:OnUPOArrived() - return self.SarmatUPO:TriggerInput("CheckUPO") + return self.BMCIK:TriggerInput("CheckUPO") end -------------------------------------------------------------------------------- @@ -304,8 +305,6 @@ function ENT:Think() self:SetPackedRatio("CabLights",self.Panel.CabLights==0.5 and 0.3 or self.Panel.CabLights) self:SetPackedBool("PanelLighting",self.Panel.PanelLights>0) - self:SetPackedBool("Headlights1",self.Panel.Headlights1 > 0) - self:SetPackedBool("Headlights2",self.Panel.Headlights2 > 0) self:SetPackedRatio("Headlight",self.Panel.Headlights2 > 0 and 1 or self.Panel.Headlights1 > 0 and 0.5 or 0) self:SetPackedBool("RedLights",self.Panel.RedLights>0) @@ -337,15 +336,6 @@ function ENT:Think() self:SetPackedBool("RingEnabled",self.BUKP.Ring) self:SetPackedBool("RingEnabledBARS",self.BARS.Ring>0) - self:SetPackedBool("DoorAlarmL",self.BUKV.CloseRing) - self:SetPackedBool("DoorAlarmR",self.BUKV.CloseRing) - - self:SetNW2Int("PassSchemesLED",self.PassSchemes.PassSchemeCurr) - self:SetNW2Int("PassSchemesLEDN",self.PassSchemes.PassSchemeNext) - self:SetPackedBool("PassSchemesLEDO",self.PassSchemes.PassSchemePath) - self:SetPackedBool("SarmatLeft",self.Panel.PassSchemePowerL) - self:SetPackedBool("SarmatRight",self.Panel.PassSchemePowerR) - self:SetPackedBool("PassengerDoor",self.PassengerDoor) self:SetPackedBool("CabinDoorLeft",self.CabinDoorLeft) self:SetPackedBool("CabinDoorRight",self.CabinDoorRight) @@ -354,8 +344,6 @@ function ENT:Think() self:SetNW2Bool("VityazLamp", self.MFDU.State~=0) self:SetPackedBool("AnnPlay",self.Panel.AnnouncerPlaying > 0) - self:SetPackedBool("AnnPlayUPO",self.Announcer.AnnTable=="AnnouncementsUPO") - --print(self.Panel.AnnouncerPlaying,self.UPO.LineOut) self:SetPackedRatio("Speed", self.Speed) self.AsyncInverter:TriggerInput("Speed",self.Speed) @@ -436,6 +424,10 @@ function ENT:OnButtonPress(button,ply) self.DoorClose:TriggerInput("Set",1) end end + if button == "RouteNumber13" then + self.RouteNumber1:TriggerInput("Set",1) + self.RouteNumber3:TriggerInput("Set",1) + end end function ENT:OnButtonRelease(button,ply) if string.find(button,"PneumaticBrakeSet") then @@ -450,4 +442,8 @@ function ENT:OnButtonRelease(button,ply) if button == "DoorRight" then self.DoorRight:TriggerInput("Set",0) end -end + if button == "RouteNumber13" then + self.RouteNumber1:TriggerInput("Set",0) + self.RouteNumber3:TriggerInput("Set",0) + end +end \ No newline at end of file diff --git a/lua/entities/gmod_subway_81-722/shared.lua b/lua/entities/gmod_subway_81-722/shared.lua index 1d6f153..5cc3c73 100644 --- a/lua/entities/gmod_subway_81-722/shared.lua +++ b/lua/entities/gmod_subway_81-722/shared.lua @@ -39,11 +39,11 @@ ENT.MirrorCams = { } ENT.AnnouncerPositions = { - {Vector(408,18.5,16),50,0.4} + {Vector(406,18.7,16),50,0.4,0x43} --[C]abin speaker } for i=1,4 do - table.insert(ENT.AnnouncerPositions,{Vector(323-(i-1)*230+37.5,47 ,44),100,0.3}) - table.insert(ENT.AnnouncerPositions,{Vector(323-(i-1)*230,-47,44),100,0.3}) + table.insert(ENT.AnnouncerPositions,{Vector(323-(i-1)*230+37.5,47,44),100,1,0x4C}) --[L]eft side speakers + table.insert(ENT.AnnouncerPositions,{Vector(323-(i-1)*230,-47,44),100,1,0x52}) --[R]ight side speakers end ENT.Cameras = { @@ -204,9 +204,6 @@ function ENT:InitializeSounds() self.SoundNames["door_cab_open"] = "subway_trains/common/door/cab/door_open.mp3" self.SoundNames["door_cab_close"] = "subway_trains/common/door/cab/door_close.mp3" - self.SoundNames["door_alarm"] = "subway_trains/722/door_alarm.mp3" - self.SoundPositions["door_alarm"] = {485,1e9,Vector(0,0,0),0.2} - self.SoundNames["doors"] = "subway_trains/722/door_start.mp3" self.SoundNames["doorl"] = {loop=true,"subway_trains/722/door_loop.wav"} self.SoundPositions["doors"] = {300,1e9,Vector(0,0,0),0.2} @@ -217,8 +214,8 @@ function ENT:InitializeSounds() self.SoundPositions["door"..i.."x"..k.."c"] = {485,1e9,GetDoorPosition(i,k),0.2} end end - self.SoundNames["door_alarm"] = {"subway_trains/722/door_alarm.mp3"} - self.SoundPositions["door_alarm"] = {485,1e9,Vector(0,0,0),0.25} + self.SoundNames["door_alarm"] = {loop=1.1,"subway_trains/722/door_alarm_start.mp3","subway_trains/722/door_alarm_loop.wav","subway_trains/722/door_alarm_end.mp3"} + self.SoundPositions["door_alarm"] = {485,1e9,Vector(0,0,0),0.35} self.SoundNames["epk_brake"] = {loop=true,"subway_trains/common/pneumatic/epv_loop.wav"} @@ -248,13 +245,15 @@ function ENT:InitializeSounds() end for k,v in ipairs(self.AnnouncerPositions) do self.SoundNames["announcer_noise1_"..k] = {loop=true,"subway_announcers/upo/noiseS1.wav"} - self.SoundPositions["announcer_noise1_"..k] = {v[2] or 300,1e9,v[1],v[3]*0.2} + self.SoundPositions["announcer_noise1_"..k] = {v[2] or 300,1e9,v[1],v[3]*0.1} self.SoundNames["announcer_noise2_"..k] = {loop=true,"subway_announcers/upo/noiseS2.wav"} - self.SoundPositions["announcer_noise2_"..k] = {v[2] or 300,1e9,v[1],v[3]*0.2} + self.SoundPositions["announcer_noise2_"..k] = {v[2] or 300,1e9,v[1],v[3]*0.1} self.SoundNames["announcer_noise3_"..k] = {loop=true,"subway_announcers/upo/noiseS3.wav"} - self.SoundPositions["announcer_noise3_"..k] = {v[2] or 300,1e9,v[1],v[3]*0.2} + self.SoundPositions["announcer_noise3_"..k] = {v[2] or 300,1e9,v[1],v[3]*0.1} self.SoundNames["announcer_noiseW"..k] = {loop=true,"subway_announcers/upo/noiseW.wav"} - self.SoundPositions["announcer_noiseW"..k] = {v[2] or 300,1e9,v[1],v[3]*0.2} + self.SoundPositions["announcer_noiseW"..k] = {v[2] or 300,1e9,v[1],v[3]*0.1} + self.SoundNames["announcer_sarmat_start"..k] = {"subway_announcers/sarmat_upo/sarmat_start.mp3"} + self.SoundPositions["announcer_sarmat_start"..k] = {v[2] or 300,1e9,v[1],v[3]} end end function ENT:InitializeSystems() @@ -267,7 +266,7 @@ function ENT:InitializeSystems() self:LoadSystem("BUKP","81_722_BUKP") self:LoadSystem("MFDU","81_722_MFDU") self:LoadSystem("BUKV","81_722_BUKV") - self:LoadSystem("RouteNumberSys","81_722_RouteNumber") + self:LoadSystem("TNM","81_722_TNM") self:LoadSystem("BARS","81_722_BARS") self:LoadSystem("ALSCoil") @@ -281,10 +280,10 @@ function ENT:InitializeSystems() self:LoadSystem("Panel","81_722_Panel") self:LoadSystem("Announcer","81_71_Announcer", "AnnouncementsSarmatUPO") - self:LoadSystem("SarmatUPO","81_722_sarmat") + self:LoadSystem("BMCIK","81_722_BMCIK") self:LoadSystem("UPO","81_71_UPO") - self:LoadSystem("Tickers","81_722_Tickers") - self:LoadSystem("PassSchemes","81_722_PassScheme") + self:LoadSystem("BIT","81_722_BIT") + self:LoadSystem("BNT","81_722_BNT") end @@ -378,6 +377,10 @@ ENT.Spawner = { ent.CabinDoorRight = val==4 and first ent.PassengerDoor = val==4 ent.RearDoor = val==4 + + ent.BMCIK.Announcer.Line = 1 + ent.BMCIK.Announcer.Path = not first + ent.BMCIK.Announcer.PathSel = not first else ent.FrontDoor = val==4 ent.RearDoor = val==4 diff --git a/lua/entities/gmod_subway_81-723/cl_init.lua b/lua/entities/gmod_subway_81-723/cl_init.lua index 060255e..ae4de59 100644 --- a/lua/entities/gmod_subway_81-723/cl_init.lua +++ b/lua/entities/gmod_subway_81-723/cl_init.lua @@ -440,42 +440,42 @@ ENT.Lights = { [20] = { "light",Vector(-46.4,-66,28.1)+Vector(0,-0.8,-4.1), Angle(0,0,0), Color(40,240,122), brightness = 0.3, scale = 0.1, texture = "sprites/light_glow02.vmt" }, } -ENT.ButtonMap["Tickers1"] = { - pos = Vector(-455.4,-11.1,52.8), +ENT.ButtonMap["BIT1"] = { + pos = Vector(-455.75,-10.92504,52.35969), ang = Angle(0,90,90), - width = 300, - height = 64, - scale = 0.094, - hideseat=1.5, + width = 1024, + height = 192, + scale = 0.026947, + hideseat = 1.5 } -ENT.ButtonMap["Tickers2"] = { - pos = Vector(2,-11.3,52.5), - ang = Angle(0,90,90+10), - width = 300, - height = 64, - scale = 0.099, - hideseat=1.5, +ENT.ButtonMap["BIT2"] = { + pos = Vector(1.55365,-10.92493,51.99417), + ang = Angle(0,90,97), + width = 1024, + height = 192, + scale = 0.026947, + hideseat = 1.5 } -ENT.ButtonMap["Tickers3"] = { - pos = Vector(-5,11.3,52.7), - ang = Angle(0,-90,90+10), - width = 300, - height = 64, - scale = 0.1, - hideseat=1.5, +ENT.ButtonMap["BIT3"] = { + pos = Vector(-4.83291,10.92509,51.99417), + ang = Angle(0,-90,97), + width = 1024, + height = 192, + scale = 0.026947, + hideseat = 1.5 } -ENT.ButtonMap["Tickers4"] = { - pos = Vector(449.3,11.1,52.8), +ENT.ButtonMap["BIT4"] = { + pos = Vector(449.44,10.92504,52.35969), ang = Angle(0,-90,90), - width = 300, - height = 64, - scale = 0.094, - hideseat=1.5, + width = 1024, + height = 192, + scale = 0.026947, + hideseat = 1.5 } function ENT:Initialize() self.BaseClass.Initialize(self) - self.Tickers = self:CreateRT("721Tickers",1024,128) + self.BITScr = self:CreateRT("722BIT",1024,256) self.FrontLeak = 0 self.RearLeak = 0 @@ -484,7 +484,6 @@ function ENT:Initialize() self.PreviousCompressorState = false self.CompressorVol = 0 self.ParkingBrake = 0 - self.BPSNBuzzVolume = 0 end function ENT:UpdateWagonNumber() local count = math.max(4,math.ceil(math.log10(self.WagonNumber+1))) @@ -505,17 +504,22 @@ function ENT:UpdateWagonNumber() --end end end +local function getBitValue(value, offset, bitCount) + local mask = bit.lshift(bit.lshift(1,bitCount)-1,offset) + return bit.rshift(bit.band(value,mask),offset) +end function ENT:Think() self.BaseClass.Think(self) if not self.RenderClientEnts or self.CreatingCSEnts then return end + local sarmatInvert = self:GetNW2Bool("SarmatInvert") if not self.PassSchemesDone then local sarmat,sarmatr = self.ClientEnts.sarmat,self.ClientEnts.sarmatr local scheme = Metrostroi.Skins["722_schemes"] and Metrostroi.Skins["722_schemes"][self.Scheme] if IsValid(sarmat) and IsValid(sarmatr) and scheme then - if self:GetNW2Bool("SarmatInvert") then + if sarmatInvert then sarmat:SetSubMaterial(0,scheme[2]) sarmatr:SetSubMaterial(0,scheme[1]) else @@ -530,12 +534,13 @@ function ENT:Think() self.PassSchemesDone = false self.Scheme = self:GetNW2Int("Scheme",1) end - if self.InvertSchemes ~= self:GetNW2Bool("SarmatInvert",false) then + if self.InvertSchemes ~= sarmatInvert then self.PassSchemesDone=false - self.InvertSchemes = self:GetNW2Bool("SarmatInvert",false) + self.InvertSchemes = sarmatInvert end local passlight = self:GetPackedRatio("SalonLighting") + self:ShowHideSmooth("lamps_salon",passlight) self:SetLightPower(11,passlight > 0, passlight) self:SetLightPower(12,passlight > 0, passlight) self:SetLightPower(13,passlight > 0, passlight) @@ -551,44 +556,54 @@ function ENT:Think() self:SetLightPower(17,BortBV,1) self:SetLightPower(20,BortBV,1) - self:ShowHideSmooth("lamps_salon",self:GetPackedRatio("SalonLighting")) - self:ShowHide("doorl_l",self:GetPackedBool("DoorAlarmL")) - self:ShowHide("doorl_r",self:GetPackedBool("DoorAlarmR")) + local doorAlarm = self:GetNW2Int("BNT:DoorAlarm") + self:SetSoundState("door_alarm",getBitValue(doorAlarm,0,1),1) + self:ShowHide("doorl_l",getBitValue(doorAlarm,1,1) > 0) + self:ShowHide("doorl_r",getBitValue(doorAlarm,2,1) > 0) self:Animate("FrontBrake", self:GetNW2Bool("FbI") and 0 or 1,0,1, 3, false) self:Animate("FrontTrain", self:GetNW2Bool("FtI") and 1 or 0,0,1, 3, false) self:Animate("RearBrake", self:GetNW2Bool("RbI") and 0 or 1,0,1, 3, false) self:Animate("RearTrain", self:GetNW2Bool("RtI") and 1 or 0,0,1, 3, false) - local led_back = self:GetPackedBool("PassSchemesLEDO",false) - if self:GetPackedBool("SarmatInvert",false) then led_back = not led_back end - local sleft,sright = self:GetPackedBool("SarmatLeft"),self:GetPackedBool("SarmatRight") - for i=1,4 do - self:ShowHide("led_l_f"..i,not led_back and sleft) - self:ShowHide("led_l_b"..i,led_back and sleft) - self:ShowHide("led_r_f"..i,not led_back and sright) - self:ShowHide("led_r_b"..i,led_back and sright) + local bntL = self:GetNW2Int("BNT:Left") + local bntR = self:GetNW2Int("BNT:Right") + local bntPowerL = getBitValue(bntL,0,1) + local bntPowerR = getBitValue(bntR,0,1) + local initL,initR = getBitValue(bntL,1,1) > 0, getBitValue(bntR,1,1) > 0 + local currL,currR = getBitValue(bntL,9,6),getBitValue(bntR,9,6) + + local invL,invR = getBitValue(bntL,2,1) > 0, getBitValue(bntR,2,1) > 0 + if sarmatInvert then + invL = not invL + invR = not invR end - local scurr = self:GetNW2Int("PassSchemesLED") - local snext = self:GetNW2Int("PassSchemesLEDN") - local led = scurr - if snext ~= 0 and CurTime()%2 > 1 then led = led + snext end - if scurr < 0 then led = math.floor(CurTime()%16.5*2) end - if led_back then - if sleft then - for i=1,4 do if IsValid(self.ClientEnts["led_l_b"..i]) then self.ClientEnts["led_l_b"..i]:SetSkin(math.Clamp(led-((i-1)*8),0,8)) end end + + if initL then + local nextL = getBitValue(bntL,3,6) + if nextL == 0 then nextL = -1 end + if CurTime()%2>1 then + currL = currL + nextL end - if sright then - for i=1,4 do if IsValid(self.ClientEnts["led_r_b"..i]) then self.ClientEnts["led_r_b"..i]:SetSkin(math.Clamp(led-((i-1)*8),0,8)) end end - end - else - if sleft then - for i=1,4 do if IsValid(self.ClientEnts["led_l_f"..i]) then self.ClientEnts["led_l_f"..i]:SetSkin(math.Clamp(led-((i-1)*8),0,8)) end end - end - if sright then - for i=1,4 do if IsValid(self.ClientEnts["led_r_f"..i]) then self.ClientEnts["led_r_f"..i]:SetSkin(math.Clamp(led-((i-1)*8),0,8)) end end + end + if initR then + local nextR = getBitValue(bntR,3,6) + if nextR == 0 then nextR = -1 end + if CurTime()%2>1 then + currR = currR + nextR end end + for i=1,4 do + self:ShowHide("led_l_f"..i,not invL) + self:ShowHide("led_l_b"..i,invL) + self:ShowHide("led_r_f"..i,not invR) + self:ShowHide("led_r_b"..i,invR) + + if IsValid(self.ClientEnts["led_l_f"..i]) then self.ClientEnts["led_l_f"..i]:SetSkin(math.Clamp(currL-((i-1)*8),0,8)) end + if IsValid(self.ClientEnts["led_l_b"..i]) then self.ClientEnts["led_l_b"..i]:SetSkin(math.Clamp(currL-((i-1)*8),0,8)) end + if IsValid(self.ClientEnts["led_r_f"..i]) then self.ClientEnts["led_r_f"..i]:SetSkin(math.Clamp(currR-((i-1)*8),0,8)) end + if IsValid(self.ClientEnts["led_r_b"..i]) then self.ClientEnts["led_r_b"..i]:SetSkin(math.Clamp(currR-((i-1)*8),0,8)) end + end local playL = false local playR = false @@ -633,7 +648,6 @@ function ENT:Think() --print(self.DoorSoundState) self:SetSoundState("doorl",self.DoorSoundState or 0,1) - local door_f = self:GetPackedBool("FrontDoor") local door_b = self:GetPackedBool("RearDoor") local door_cab_f = self:Animate("door_cab_f",door_f and 1 or -0.05,1,0.75, 8, 0.05) @@ -699,7 +713,6 @@ function ENT:Think() self:SetSoundState("rolling_60",rollingi*rol60,1) self:SetSoundState("rolling_70",rollingi*rol70,1) - local rol10 = math.Clamp(speed/15,0,1)*(1-math.Clamp((speed-18)/35,0,1)) local rol10p = Lerp((speed-15)/14,0.6,0.78) local rol40 = math.Clamp((speed-18)/35,0,1)*(1-math.Clamp((speed-55)/40,0,1)) @@ -728,51 +741,60 @@ function ENT:Think() self:SetSoundState("chopper", tunstreet*self:GetPackedRatio("chopper"), 1) local work = self:GetPackedBool("AnnPlay") - local UPO = work and self:GetPackedBool("AnnPlayUPO") + local UPO = work and self.Announcer.AnnTable == "AnnouncementsUPO" + local noise = self:GetNW2Int("AnnouncerNoise") + + local volBMCIK = self:GetNW2Int("BMCIK:VolCab",0)/10 + local volBNT = self:GetNW2Int("BNT:Volumes",0) - local noise = self:GetNW2Int("AnnouncerNoise", -1) - local volume = self:GetNW2Float("UPOVolume",1) - local noisevolume = self:GetNW2Float("UPONoiseVolume",1) - local buzzvolume = volume - if self.Sounds["announcer1"] and IsValid(self.Sounds["announcer1"]) then buzzvolume = UPO and (1-(self.Sounds["announcer1"]:GetLevel())*math.Rand(0.9,3))*buzzvolume*2 or 0 end - if self.BPSNBuzzVolume > buzzvolume then - self.BPSNBuzzVolume = math.Clamp(self.BPSNBuzzVolume + 8*(buzzvolume-self.BPSNBuzzVolume)*dT,0.1,1) + local volSalon = 0 + local noisevolume = 0 + if UPO then + noisevolume = self:GetNW2Float("UPONoiseVolume",1) + volSalon = getBitValue(volBNT,4,4)/10*self:GetNW2Float("UPOVolume",1) else - self.BPSNBuzzVolume = math.Clamp(self.BPSNBuzzVolume + 0.4*(buzzvolume-self.BPSNBuzzVolume)*dT,0.1,1) + volSalon = getBitValue(volBNT,0,4)/10 end for k,v in ipairs(self.AnnouncerPositions) do - self:SetSoundState("announcer_noiseW"..k,UPO and noisevolume*volume*0.7 or 0,1) - for i=1,3 do - self:SetSoundState(Format("announcer_noise%d_%d",i,k),(UPO and i==noise) and volume*self.BPSNBuzzVolume*self:GetNW2Float("UPOBuzzVolume",1)*0.7 or 0,1) + local targetVol = 0 + if work then + if v[4] == 0x4C then -- [L]eft side + targetVol = v[3]*volSalon*bntPowerL + elseif v[4] == 0x52 then -- [R]ight side + targetVol = v[3]*volSalon*bntPowerR + elseif v[4] == 0x43 then -- [C]abin + targetVol = v[3]*volBMCIK + end end - if IsValid(self.Sounds["announcer"..k]) then self.Sounds["announcer"..k]:SetVolume(work and v[3]*(UPO and volume or 1) or 0) end + self:SetSoundState("announcer_noiseW"..k,targetVol*noisevolume,1) + for i=1,3 do + self:SetSoundState(Format("announcer_noise%d_%d",i,k),(UPO and i==noise) and targetVol*noisevolume or 0,1) + end + + if IsValid(self.Sounds["announcer"..k]) then self.Sounds["announcer"..k]:SetVolume(targetVol) end end end -function ENT:OnAnnouncer(volume) - local work = self:GetPackedBool("AnnPlay") - local UPO = work and self:GetPackedBool("AnnPlayUPO") +-- function ENT:OnAnnouncer(volume) +-- local work = self:GetPackedBool("AnnPlay") +-- local UPO = work and self:GetPackedBool("AnnPlayUPO") - return work and volume*(UPO and self:GetNW2Float("UPOVolume",1) or 1) or 0 -end +-- return work and volume*(UPO and self:GetNW2Float("UPOVolume",1) or 1) or 0 +-- end function ENT:Draw() self.BaseClass.Draw(self) end function ENT:DrawPost() - self.RTMaterial:SetTexture("$basetexture", self.Tickers) + self.RTMaterial:SetTexture("$basetexture", self.BITScr) surface.SetMaterial(self.RTMaterial) - surface.SetDrawColor(255,255,255) + surface.SetDrawColor(255,255,255,200) for i=1,4 do - self:DrawOnPanel("Tickers"..i,function(...) - if (i==2 or i==3) then - surface.DrawTexturedRectRotated(245,32,490,64,0) - else - surface.DrawTexturedRectRotated(256,32,512,64,0) - end + self:DrawOnPanel("BIT"..i,function(...) + surface.DrawTexturedRectRotated(512,128,1024,256,0) end) end end diff --git a/lua/entities/gmod_subway_81-723/init.lua b/lua/entities/gmod_subway_81-723/init.lua index 8b3c517..e216f41 100644 --- a/lua/entities/gmod_subway_81-723/init.lua +++ b/lua/entities/gmod_subway_81-723/init.lua @@ -90,9 +90,6 @@ function ENT:Initialize() self.FrontDoor = false self.RearDoor = false - - self:SetNW2Float("UPONoiseVolume",math.Rand(0,0.3)) - self:SetNW2Float("UPOVolume",math.Rand(0.8,1)) end -------------------------------------------------------------------------------- @@ -115,12 +112,6 @@ function ENT:Think() --self:SetPackedBool("BattPressed",self.BUKV.BatteryPressed) - self:SetNW2Int("PassSchemesLED",self.PassSchemes.PassSchemeCurr) - self:SetNW2Int("PassSchemesLEDN",self.PassSchemes.PassSchemeNext) - self:SetPackedBool("PassSchemesLEDO",self.PassSchemes.PassSchemePath) - self:SetPackedBool("SarmatLeft",self.Panel.PassSchemePowerL) - self:SetPackedBool("SarmatRight",self.Panel.PassSchemePowerR) - self:SetPackedBool("CompressorWork",self.Pneumatic.Compressor) --self:SetPackedRatio("Cran", self.Pneumatic.DriverValvePosition) @@ -135,17 +126,7 @@ function ENT:Think() self:SetPackedBool("BortLSD",self.Panel.DoorsW>0) self:SetPackedBool("BortBV",self.Panel.GRP>0) - self:SetPackedBool("DoorAlarmL",self.BUKV.CloseRing) - self:SetPackedBool("DoorAlarmR",self.BUKV.CloseRing) - - self:SetNW2Int("PassSchemesLED",self.PassSchemes.PassSchemeCurr) - self:SetNW2Int("PassSchemesLEDN",self.PassSchemes.PassSchemeNext) - self:SetPackedBool("PassSchemesLEDO",self.PassSchemes.PassSchemePath) - self:SetPackedBool("SarmatLeft",self.Panel.PassSchemePowerL) - self:SetPackedBool("SarmatRight",self.Panel.PassSchemePowerR) - self:SetPackedBool("AnnPlay",self.Panel.AnnouncerPlaying > 0) - self:SetPackedBool("AnnPlayUPO",self.Announcer.AnnTable=="AnnouncementsUPO") self.AsyncInverter:TriggerInput("Speed",self.Speed) if IsValid(self.FrontBogey) and IsValid(self.RearBogey) and not self.IgnoreEngine then diff --git a/lua/entities/gmod_subway_81-723/shared.lua b/lua/entities/gmod_subway_81-723/shared.lua index 4c07eea..90e57ae 100644 --- a/lua/entities/gmod_subway_81-723/shared.lua +++ b/lua/entities/gmod_subway_81-723/shared.lua @@ -33,6 +33,12 @@ for i=0,3 do table.insert(ENT.RightDoorPositions,GetDoorPosition(i,0)) end +ENT.AnnouncerPositions = {} +for i=1,4 do + table.insert(ENT.AnnouncerPositions,{Vector(323-(i-1)*230+37.5,47,44),100,1,0x4C}) --[L]eft side speakers + table.insert(ENT.AnnouncerPositions,{Vector(323-(i-1)*230,-47,44),100,1,0x52}) --[R]ight side speakers +end + function ENT:InitializeSounds() self.BaseClass.InitializeSounds(self) self.SoundNames["test_async1"] = {"subway_trains/722/engines/inverter_1000.wav",loop = true} @@ -105,8 +111,8 @@ function ENT:InitializeSounds() self.SoundNames["sf_on"] = "subway_trains/722/switches/sf_on.mp3" self.SoundNames["sf_off"] = "subway_trains/722/switches/sf_off.mp3" - self.SoundNames["door_alarm"] = "subway_trains/722/door_alarm.mp3" - self.SoundPositions["door_alarm"] = {800,1e9,Vector(0,0,0),0.5} + self.SoundNames["door_alarm"] = {loop=1.1,"subway_trains/722/door_alarm_start.mp3","subway_trains/722/door_alarm_loop.wav","subway_trains/722/door_alarm_end.mp3"} + self.SoundPositions["door_alarm"] = {485,1e9,Vector(0,0,0),0.35} self.SoundNames["door_cab_open"] = "subway_trains/common/door/cab/door_open.mp3" self.SoundNames["door_cab_close"] = "subway_trains/common/door/cab/door_close.mp3" @@ -121,8 +127,6 @@ function ENT:InitializeSounds() self.SoundPositions["door"..i.."x"..k.."c"] = {800,1e9,GetDoorPosition(i,k),0.2} end end - self.SoundNames["door_alarm"] = {"subway_trains/722/door_alarm.mp3"} - self.SoundPositions["door_alarm"] = {800,1e9,Vector(0,0,0),0.5} for i = 1,10 do local id1 = Format("b1tunnel_%d",i) local id2 = Format("b2tunnel_%d",i) @@ -133,13 +137,15 @@ function ENT:InitializeSounds() end for k,v in ipairs(self.AnnouncerPositions) do self.SoundNames["announcer_noise1_"..k] = {loop=true,"subway_announcers/upo/noiseS1.wav"} - self.SoundPositions["announcer_noise1_"..k] = {v[2] or 300,1e9,v[1],v[3]*0.2} + self.SoundPositions["announcer_noise1_"..k] = {v[2] or 300,1e9,v[1],v[3]*0.1} self.SoundNames["announcer_noise2_"..k] = {loop=true,"subway_announcers/upo/noiseS2.wav"} - self.SoundPositions["announcer_noise2_"..k] = {v[2] or 300,1e9,v[1],v[3]*0.2} + self.SoundPositions["announcer_noise2_"..k] = {v[2] or 300,1e9,v[1],v[3]*0.1} self.SoundNames["announcer_noise3_"..k] = {loop=true,"subway_announcers/upo/noiseS3.wav"} - self.SoundPositions["announcer_noise3_"..k] = {v[2] or 300,1e9,v[1],v[3]*0.2} + self.SoundPositions["announcer_noise3_"..k] = {v[2] or 300,1e9,v[1],v[3]*0.1} self.SoundNames["announcer_noiseW"..k] = {loop=true,"subway_announcers/upo/noiseW.wav"} - self.SoundPositions["announcer_noiseW"..k] = {v[2] or 300,1e9,v[1],v[3]*0.2} + self.SoundPositions["announcer_noiseW"..k] = {v[2] or 300,1e9,v[1],v[3]*0.1} + self.SoundNames["announcer_sarmat_start"..k] = {"subway_announcers/sarmat_upo/sarmat_start.mp3"} + self.SoundPositions["announcer_sarmat_start"..k] = {v[2] or 300,1e9,v[1],v[3]} end end @@ -158,21 +164,14 @@ function ENT:InitializeSystems() self:LoadSystem("Panel","81_723_Panel") self:LoadSystem("Announcer","81_71_Announcer", "AnnouncementsSarmatUPO") - self:LoadSystem("Tickers","81_722_Tickers") - self:LoadSystem("PassSchemes","81_722_PassScheme") + self:LoadSystem("BIT","81_722_BIT") + self:LoadSystem("BNT","81_722_BNT") end function ENT:PostInitializeSystems() self.Electric:TriggerInput("Type",self.Electric.T723) end - -ENT.AnnouncerPositions = { -} -for i=1,4 do - table.insert(ENT.AnnouncerPositions,{Vector(323-(i-1)*230+37.5,47 ,44),100,0.1}) - table.insert(ENT.AnnouncerPositions,{Vector(323-(i-1)*230,-47,44),100,0.1}) -end --------------------------------------------------- -- Defined train information -- Types of wagon(for wagon limit system): diff --git a/lua/entities/gmod_subway_81-724/cl_init.lua b/lua/entities/gmod_subway_81-724/cl_init.lua index 1a800ac..355bbc1 100644 --- a/lua/entities/gmod_subway_81-724/cl_init.lua +++ b/lua/entities/gmod_subway_81-724/cl_init.lua @@ -436,49 +436,48 @@ ENT.Lights = { [18] = { "light",Vector(-46.4,-66,28.1)+Vector(0,-0,4.1), Angle(0,0,0), Color(254,254,254), brightness = 0.4, scale = 0.1, texture = "sprites/light_glow02.vmt" }, [19] = { "light",Vector(-46.4,-66,28.1)+Vector(0,-0.4,-0), Angle(0,0,0), Color(254,210,18), brightness = 0.3, scale = 0.1, texture = "sprites/light_glow02.vmt" }, } -ENT.ButtonMap["Tickers1"] = { - pos = Vector(-455.4,-11.1,52.8), +ENT.ButtonMap["BIT1"] = { + pos = Vector(-455.75,-10.92504,52.35969), ang = Angle(0,90,90), - width = 300, - height = 64, - scale = 0.094, - hideseat=1.5, + width = 1024, + height = 192, + scale = 0.026947, + hideseat = 1.5 } -ENT.ButtonMap["Tickers2"] = { - pos = Vector(2,-11.3,52.5), - ang = Angle(0,90,90+10), - width = 300, - height = 64, - scale = 0.099, - hideseat=1.5, +ENT.ButtonMap["BIT2"] = { + pos = Vector(1.55365,-10.92493,51.99417), + ang = Angle(0,90,97), + width = 1024, + height = 192, + scale = 0.026947, + hideseat = 1.5 } -ENT.ButtonMap["Tickers3"] = { - pos = Vector(-5,11.3,52.7), - ang = Angle(0,-90,90+10), - width = 300, - height = 64, - scale = 0.1, - hideseat=1.5, +ENT.ButtonMap["BIT3"] = { + pos = Vector(-4.83291,10.92509,51.99417), + ang = Angle(0,-90,97), + width = 1024, + height = 192, + scale = 0.026947, + hideseat = 1.5 } -ENT.ButtonMap["Tickers4"] = { - pos = Vector(449.3,11.1,52.8), +ENT.ButtonMap["BIT4"] = { + pos = Vector(449.44,10.92504,52.35969), ang = Angle(0,-90,90), - width = 300, - height = 64, - scale = 0.094, - hideseat=1.5, + width = 1024, + height = 192, + scale = 0.026947, + hideseat = 1.5 } function ENT:Initialize() self.BaseClass.Initialize(self) - self.Tickers = self:CreateRT("721Tickers",1024,128) + self.BITScr = self:CreateRT("722BIT",1024,256) self.ReleasedPdT = 0 self.FrontLeak = 0 self.RearLeak = 0 self.ParkingBrake = 0 - self.BPSNBuzzVolume = 0 end function ENT:UpdateWagonNumber() local count = math.max(4,math.ceil(math.log10(self.WagonNumber+1))) @@ -499,17 +498,22 @@ function ENT:UpdateWagonNumber() --end end end +local function getBitValue(value, offset, bitCount) + local mask = bit.lshift(bit.lshift(1,bitCount)-1,offset) + return bit.rshift(bit.band(value,mask),offset) +end function ENT:Think() self.BaseClass.Think(self) if not self.RenderClientEnts or self.CreatingCSEnts then return end + local sarmatInvert = self:GetNW2Bool("SarmatInvert") if not self.PassSchemesDone then local sarmat,sarmatr = self.ClientEnts.sarmat,self.ClientEnts.sarmatr local scheme = Metrostroi.Skins["722_schemes"] and Metrostroi.Skins["722_schemes"][self.Scheme] if IsValid(sarmat) and IsValid(sarmatr) and scheme then - if self:GetNW2Bool("SarmatInvert") then + if sarmatInvert then sarmat:SetSubMaterial(0,scheme[2]) sarmatr:SetSubMaterial(0,scheme[1]) else @@ -524,12 +528,13 @@ function ENT:Think() self.PassSchemesDone = false self.Scheme = self:GetNW2Int("Scheme",1) end - if self.InvertSchemes ~= self:GetNW2Bool("SarmatInvert",false) then + if self.InvertSchemes ~= sarmatInvert then self.PassSchemesDone=false - self.InvertSchemes = self:GetNW2Bool("SarmatInvert",false) + self.InvertSchemes = sarmatInvert end local passlight = self:GetPackedRatio("SalonLighting") + self:ShowHideSmooth("lamps_salon",passlight) self:SetLightPower(11,passlight > 0, passlight) self:SetLightPower(12,passlight > 0, passlight) self:SetLightPower(13,passlight > 0, passlight) @@ -545,44 +550,54 @@ function ENT:Think() self:ShowHide("bortlamp_pneumo",self:GetPackedBool("BortPneumo")) self:ShowHide("bortlamp_lsd",self:GetPackedBool("BortLSD")) - self:ShowHideSmooth("lamps_salon",self:GetPackedRatio("SalonLighting")) - self:ShowHide("doorl_l",self:GetPackedBool("DoorAlarmL")) - self:ShowHide("doorl_r",self:GetPackedBool("DoorAlarmR")) + local doorAlarm = self:GetNW2Int("BNT:DoorAlarm") + self:SetSoundState("door_alarm",getBitValue(doorAlarm,0,1),1) + self:ShowHide("doorl_l",getBitValue(doorAlarm,1,1) > 0) + self:ShowHide("doorl_r",getBitValue(doorAlarm,2,1) > 0) self:Animate("FrontBrake", self:GetNW2Bool("FbI") and 0 or 1,0,1, 3, false) self:Animate("FrontTrain", self:GetNW2Bool("FtI") and 1 or 0,0,1, 3, false) self:Animate("RearBrake", self:GetNW2Bool("RbI") and 0 or 1,0,1, 3, false) self:Animate("RearTrain", self:GetNW2Bool("RtI") and 1 or 0,0,1, 3, false) - local led_back = self:GetPackedBool("PassSchemesLEDO",false) - if self:GetPackedBool("SarmatInvert",false) then led_back = not led_back end - local sleft,sright = self:GetPackedBool("SarmatLeft"),self:GetPackedBool("SarmatRight") - for i=1,4 do - self:ShowHide("led_l_f"..i,not led_back and sleft) - self:ShowHide("led_l_b"..i,led_back and sleft) - self:ShowHide("led_r_f"..i,not led_back and sright) - self:ShowHide("led_r_b"..i,led_back and sright) + local bntL = self:GetNW2Int("BNT:Left") + local bntR = self:GetNW2Int("BNT:Right") + local bntPowerL = getBitValue(bntL,0,1) + local bntPowerR = getBitValue(bntR,0,1) + local initL,initR = getBitValue(bntL,1,1) > 0, getBitValue(bntR,1,1) > 0 + local currL,currR = getBitValue(bntL,9,6),getBitValue(bntR,9,6) + + local invL,invR = getBitValue(bntL,2,1) > 0, getBitValue(bntR,2,1) > 0 + if sarmatInvert then + invL = not invL + invR = not invR end - local scurr = self:GetNW2Int("PassSchemesLED") - local snext = self:GetNW2Int("PassSchemesLEDN") - local led = scurr - if snext ~= 0 and CurTime()%2 > 1 then led = led + snext end - if scurr < 0 then led = math.floor(CurTime()%16.5*2) end - if led_back then - if sleft then - for i=1,4 do if IsValid(self.ClientEnts["led_l_b"..i]) then self.ClientEnts["led_l_b"..i]:SetSkin(math.Clamp(led-((i-1)*8),0,8)) end end + + if initL then + local nextL = getBitValue(bntL,3,6) + if nextL == 0 then nextL = -1 end + if CurTime()%2>1 then + currL = currL + nextL end - if sright then - for i=1,4 do if IsValid(self.ClientEnts["led_r_b"..i]) then self.ClientEnts["led_r_b"..i]:SetSkin(math.Clamp(led-((i-1)*8),0,8)) end end - end - else - if sleft then - for i=1,4 do if IsValid(self.ClientEnts["led_l_f"..i]) then self.ClientEnts["led_l_f"..i]:SetSkin(math.Clamp(led-((i-1)*8),0,8)) end end - end - if sright then - for i=1,4 do if IsValid(self.ClientEnts["led_r_f"..i]) then self.ClientEnts["led_r_f"..i]:SetSkin(math.Clamp(led-((i-1)*8),0,8)) end end + end + if initR then + local nextR = getBitValue(bntR,3,6) + if nextR == 0 then nextR = -1 end + if CurTime()%2>1 then + currR = currR + nextR end end + for i=1,4 do + self:ShowHide("led_l_f"..i,not invL) + self:ShowHide("led_l_b"..i,invL) + self:ShowHide("led_r_f"..i,not invR) + self:ShowHide("led_r_b"..i,invR) + + if IsValid(self.ClientEnts["led_l_f"..i]) then self.ClientEnts["led_l_f"..i]:SetSkin(math.Clamp(currL-((i-1)*8),0,8)) end + if IsValid(self.ClientEnts["led_l_b"..i]) then self.ClientEnts["led_l_b"..i]:SetSkin(math.Clamp(currL-((i-1)*8),0,8)) end + if IsValid(self.ClientEnts["led_r_f"..i]) then self.ClientEnts["led_r_f"..i]:SetSkin(math.Clamp(currR-((i-1)*8),0,8)) end + if IsValid(self.ClientEnts["led_r_b"..i]) then self.ClientEnts["led_r_b"..i]:SetSkin(math.Clamp(currR-((i-1)*8),0,8)) end + end local playL = false local playR = false @@ -689,51 +704,60 @@ function ENT:Think() self:SetSoundState("battery_off_loop", self:GetPackedBool("BattPressed") and 1 or 0,1) local work = self:GetPackedBool("AnnPlay") - local UPO = work and self:GetPackedBool("AnnPlayUPO") + local UPO = work and self.Announcer.AnnTable == "AnnouncementsUPO" + local noise = self:GetNW2Int("AnnouncerNoise") + + local volBMCIK = self:GetNW2Int("BMCIK:VolCab",0)/10 + local volBNT = self:GetNW2Int("BNT:Volumes",0) - local noise = self:GetNW2Int("AnnouncerNoise", -1) - local volume = self:GetNW2Float("UPOVolume",1) - local noisevolume = self:GetNW2Float("UPONoiseVolume",1) - local buzzvolume = volume - if self.Sounds["announcer1"] and IsValid(self.Sounds["announcer1"]) then buzzvolume = UPO and (1-(self.Sounds["announcer1"]:GetLevel())*math.Rand(0.9,3))*buzzvolume*2 or 0 end - if self.BPSNBuzzVolume > buzzvolume then - self.BPSNBuzzVolume = math.Clamp(self.BPSNBuzzVolume + 8*(buzzvolume-self.BPSNBuzzVolume)*dT,0.1,1) + local volSalon = 0 + local noisevolume = 0 + if UPO then + noisevolume = self:GetNW2Float("UPONoiseVolume",1) + volSalon = getBitValue(volBNT,4,4)/10*self:GetNW2Float("UPOVolume",1) else - self.BPSNBuzzVolume = math.Clamp(self.BPSNBuzzVolume + 0.4*(buzzvolume-self.BPSNBuzzVolume)*dT,0.1,1) + volSalon = getBitValue(volBNT,0,4)/10 end for k,v in ipairs(self.AnnouncerPositions) do - self:SetSoundState("announcer_noiseW"..k,UPO and noisevolume*volume*0.7 or 0,1) - for i=1,3 do - self:SetSoundState(Format("announcer_noise%d_%d",i,k),(UPO and i==noise) and volume*self.BPSNBuzzVolume*self:GetNW2Float("UPOBuzzVolume",1)*0.7 or 0,1) + local targetVol = 0 + if work then + if v[4] == 0x4C then -- [L]eft side + targetVol = v[3]*volSalon*bntPowerL + elseif v[4] == 0x52 then -- [R]ight side + targetVol = v[3]*volSalon*bntPowerR + elseif v[4] == 0x43 then -- [C]abin + targetVol = v[3]*volBMCIK + end end - if IsValid(self.Sounds["announcer"..k]) then self.Sounds["announcer"..k]:SetVolume(work and v[3]*(UPO and volume or 1) or 0) end + self:SetSoundState("announcer_noiseW"..k,targetVol*noisevolume,1) + for i=1,3 do + self:SetSoundState(Format("announcer_noise%d_%d",i,k),(UPO and i==noise) and targetVol*noisevolume or 0,1) + end + + if IsValid(self.Sounds["announcer"..k]) then self.Sounds["announcer"..k]:SetVolume(targetVol) end end end -function ENT:OnAnnouncer(volume) - local work = self:GetPackedBool("AnnPlay") - local UPO = work and self:GetPackedBool("AnnPlayUPO") +-- function ENT:OnAnnouncer(volume) +-- local work = self:GetPackedBool("AnnPlay") +-- local UPO = work and self:GetPackedBool("AnnPlayUPO") - return work and volume*(UPO and self:GetNW2Float("UPOVolume",1) or 1) or 0 -end +-- return work and volume*(UPO and self:GetNW2Float("UPOVolume",1) or 1) or 0 +-- end function ENT:Draw() self.BaseClass.Draw(self) end function ENT:DrawPost() - self.RTMaterial:SetTexture("$basetexture", self.Tickers) + self.RTMaterial:SetTexture("$basetexture", self.BITScr) surface.SetMaterial(self.RTMaterial) - surface.SetDrawColor(255,255,255) + surface.SetDrawColor(255,255,255,200) for i=1,4 do - self:DrawOnPanel("Tickers"..i,function(...) - if (i==2 or i==3) then - surface.DrawTexturedRectRotated(245,32,490,64,0) - else - surface.DrawTexturedRectRotated(256,32,512,64,0) - end + self:DrawOnPanel("BIT"..i,function(...) + surface.DrawTexturedRectRotated(512,128,1024,256,0) end) end end diff --git a/lua/entities/gmod_subway_81-724/init.lua b/lua/entities/gmod_subway_81-724/init.lua index ab0a1ba..b071b4a 100644 --- a/lua/entities/gmod_subway_81-724/init.lua +++ b/lua/entities/gmod_subway_81-724/init.lua @@ -90,9 +90,6 @@ function ENT:Initialize() self.FrontDoor = false self.RearDoor = false - - self:SetNW2Float("UPONoiseVolume",math.Rand(0,0.3)) - self:SetNW2Float("UPOVolume",math.Rand(0.8,1)) end -------------------------------------------------------------------------------- @@ -104,12 +101,6 @@ function ENT:Think() self:SetPackedBool("BattPressed",self.BUKV.BatteryPressed) - self:SetNW2Int("PassSchemesLED",self.PassSchemes.PassSchemeCurr) - self:SetNW2Int("PassSchemesLEDN",self.PassSchemes.PassSchemeNext) - self:SetPackedBool("PassSchemesLEDO",self.PassSchemes.PassSchemePath) - self:SetPackedBool("SarmatLeft",self.Panel.PassSchemePowerL) - self:SetPackedBool("SarmatRight",self.Panel.PassSchemePowerR) - --self:SetPackedRatio("Cran", self.Pneumatic.DriverValvePosition) --self:SetPackedRatio("BL", self.Pneumatic.BrakeLinePressure/16.0) --self:SetPackedRatio("TL", self.Pneumatic.TrainLinePressure/16.0) @@ -121,11 +112,7 @@ function ENT:Think() self:SetPackedBool("BortPneumo",self.Panel.BrW>0) self:SetPackedBool("BortLSD",self.Panel.DoorsW>0) - self:SetPackedBool("DoorAlarmL",self.BUKV.CloseRing) - self:SetPackedBool("DoorAlarmR",self.BUKV.CloseRing) - self:SetPackedBool("AnnPlay",self.Panel.AnnouncerPlaying > 0) - self:SetPackedBool("AnnPlayUPO",self.Announcer.AnnTable=="AnnouncementsUPO") if IsValid(self.FrontBogey) and IsValid(self.RearBogey) and not self.IgnoreEngine then --local A = 2*self.Engines.BogeyMoment diff --git a/lua/entities/gmod_subway_81-724/shared.lua b/lua/entities/gmod_subway_81-724/shared.lua index a2a1ae4..a40edd1 100644 --- a/lua/entities/gmod_subway_81-724/shared.lua +++ b/lua/entities/gmod_subway_81-724/shared.lua @@ -33,6 +33,12 @@ for i=0,3 do table.insert(ENT.RightDoorPositions,GetDoorPosition(i,0)) end +ENT.AnnouncerPositions = {} +for i=1,4 do + table.insert(ENT.AnnouncerPositions,{Vector(323-(i-1)*230+37.5,47,44),100,1,0x4C}) --[L]eft side speakers + table.insert(ENT.AnnouncerPositions,{Vector(323-(i-1)*230,-47,44),100,1,0x52}) --[R]ight side speakers +end + function ENT:InitializeSounds() self.BaseClass.InitializeSounds(self) self.SoundNames["release"] = {loop=true,"subway_trains/722/pneumo_release2.wav"} @@ -79,9 +85,6 @@ function ENT:InitializeSounds() self.SoundNames["battery_off_loop"] = {loop=true,"subway_trains/722/battery/battery_off_loop.wav"} self.SoundPositions["battery_off_loop"] = {100,1e9,Vector(182,50,-75),0.02} - self.SoundNames["door_alarm"] = "subway_trains/722/door_alarm.mp3" - self.SoundPositions["door_alarm"] = {800,1e9,Vector(0,0,0),0.5} - self.SoundNames["door_cab_open"] = "subway_trains/common/door/cab/door_open.mp3" self.SoundNames["door_cab_close"] = "subway_trains/common/door/cab/door_close.mp3" @@ -95,8 +98,8 @@ function ENT:InitializeSounds() self.SoundPositions["door"..i.."x"..k.."c"] = {800,1e9,GetDoorPosition(i,k),0.2} end end - self.SoundNames["door_alarm"] = {"subway_trains/722/door_alarm.mp3"} - self.SoundPositions["door_alarm"] = {800,1e9,Vector(0,0,0),0.5} + self.SoundNames["door_alarm"] = {loop=1.1,"subway_trains/722/door_alarm_start.mp3","subway_trains/722/door_alarm_loop.wav","subway_trains/722/door_alarm_end.mp3"} + self.SoundPositions["door_alarm"] = {485,1e9,Vector(0,0,0),0.35} for i = 1,10 do local id1 = Format("b1tunnel_%d",i) local id2 = Format("b2tunnel_%d",i) @@ -107,13 +110,15 @@ function ENT:InitializeSounds() end for k,v in ipairs(self.AnnouncerPositions) do self.SoundNames["announcer_noise1_"..k] = {loop=true,"subway_announcers/upo/noiseS1.wav"} - self.SoundPositions["announcer_noise1_"..k] = {v[2] or 300,1e9,v[1],v[3]*0.2} + self.SoundPositions["announcer_noise1_"..k] = {v[2] or 300,1e9,v[1],v[3]*0.1} self.SoundNames["announcer_noise2_"..k] = {loop=true,"subway_announcers/upo/noiseS2.wav"} - self.SoundPositions["announcer_noise2_"..k] = {v[2] or 300,1e9,v[1],v[3]*0.2} + self.SoundPositions["announcer_noise2_"..k] = {v[2] or 300,1e9,v[1],v[3]*0.1} self.SoundNames["announcer_noise3_"..k] = {loop=true,"subway_announcers/upo/noiseS3.wav"} - self.SoundPositions["announcer_noise3_"..k] = {v[2] or 300,1e9,v[1],v[3]*0.2} + self.SoundPositions["announcer_noise3_"..k] = {v[2] or 300,1e9,v[1],v[3]*0.1} self.SoundNames["announcer_noiseW"..k] = {loop=true,"subway_announcers/upo/noiseW.wav"} - self.SoundPositions["announcer_noiseW"..k] = {v[2] or 300,1e9,v[1],v[3]*0.2} + self.SoundPositions["announcer_noiseW"..k] = {v[2] or 300,1e9,v[1],v[3]*0.1} + self.SoundNames["announcer_sarmat_start"..k] = {"subway_announcers/sarmat_upo/sarmat_start.mp3"} + self.SoundPositions["announcer_sarmat_start"..k] = {v[2] or 300,1e9,v[1],v[3]} end end @@ -132,21 +137,14 @@ function ENT:InitializeSystems() self:LoadSystem("Panel","81_724_Panel") self:LoadSystem("Announcer","81_71_Announcer", "AnnouncementsSarmatUPO") - self:LoadSystem("Tickers","81_722_Tickers") - self:LoadSystem("PassSchemes","81_722_PassScheme") + self:LoadSystem("BIT","81_722_BIT") + self:LoadSystem("BNT","81_722_BNT") end function ENT:PostInitializeSystems() self.Electric:TriggerInput("Type",self.Electric.T724) end - -ENT.AnnouncerPositions = { -} -for i=1,4 do - table.insert(ENT.AnnouncerPositions,{Vector(323-(i-1)*230+37.5,47 ,44),100,0.1}) - table.insert(ENT.AnnouncerPositions,{Vector(323-(i-1)*230,-47,44),100,0.1}) -end --------------------------------------------------- -- Defined train information -- Types(for wagon limit system): diff --git a/lua/metrostroi/maps/b50.lua b/lua/metrostroi/maps/b50.lua index 63578d3..1522da9 100644 --- a/lua/metrostroi/maps/b50.lua +++ b/lua/metrostroi/maps/b50.lua @@ -19,8 +19,8 @@ Metrostroi.AddPassSchemeTex("720","Line 2",{ "metrostroi_skins/81-720_schemes/b50_2r", }) Metrostroi.AddPassSchemeTex("722","Line 1",{ - "metrostroi_skins/81-722_schemes/b50_1", "metrostroi_skins/81-722_schemes/b50_1r", + "metrostroi_skins/81-722_schemes/b50_1", }) Metrostroi.AddPassSchemeTex("722","Line 2",{ "metrostroi_skins/81-722_schemes/b50_2", @@ -1144,8 +1144,8 @@ Metrostroi.AddSarmatUPOAnnouncer("UPO RHINO",{ odz2 = {"subway_announcers/sarmat_upo/rhino/metrostroi/odz2.mp3", 2.192400 + 0.3} }, { { - LED = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 2, 2}, - Name = "Индустриал.-Синеозёрн.", + LED = {2,2,2,2,2,2,2,2,2,2,2,2,4,2,2}, + Name = "Автозавдоская - Междустройская", Loop = false, { 108, @@ -1263,8 +1263,8 @@ Metrostroi.AddSarmatUPOAnnouncer("UPO RHINO",{ } }, { - LED = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 2, 1, 1}, - Name = "Индустриально-Авт.Юж.", + LED = {2,2,2,2,2,2,2,2,2,2,2,2,4,2,1,1}, + Name = "Автозавдоская - Автостанция Южная", Loop = false, { 108, diff --git a/lua/metrostroi/maps/crossline.lua b/lua/metrostroi/maps/crossline.lua index a174261..7780513 100644 --- a/lua/metrostroi/maps/crossline.lua +++ b/lua/metrostroi/maps/crossline.lua @@ -1,5 +1,5 @@ local Map = game.GetMap():lower() or "" -if Map:find("gm_metro_crossline_c") then +if Map:find("gm_metro_crossline_c") or Map:find("gm_metro_crossline_n") then Metrostroi.PlatformMap = "gm_metro_crossline" Metrostroi.CurrentMap = "gm_metro_crossline" else @@ -9,12 +9,12 @@ Metrostroi.AddPassSchemeTex("717_new","1 Line",{ "models/metrostroi_schemes/map_1", }) Metrostroi.AddPassSchemeTex("720","Crossline",{ - "metrostroi_skins/81-720_schemes/crossline", - "metrostroi_skins/81-720_schemes/crossliner", + "metrostroi_skins/81-720_schemes/crossline_a3", + "metrostroi_skins/81-720_schemes/crossliner_a3", }) Metrostroi.AddPassSchemeTex("722","Crossline",{ - "metrostroi_skins/81-722_schemes/crossline", - "metrostroi_skins/81-722_schemes/crossliner", + "metrostroi_skins/81-722_schemes/crossline_a3", + "metrostroi_skins/81-722_schemes/crossliner_a3", }) Metrostroi.AddLastStationTex("702",110,"models/metrostroi_schemes/destination_table_black/label_mezhdunarodnaya") Metrostroi.AddLastStationTex("702",115,"models/metrostroi_schemes/destination_table_black/label_oktyabrskaya") @@ -155,7 +155,7 @@ Metrostroi.AddANSPAnnouncer("ASNP Boiko + Pyaseckaya",{ vokzalnaya_f = {"subway_announcers/asnp/pyaseckaya/crossline/2/vokzalnaya.mp3",1.175854}, },{ { --МАРШРУТ - LED = {5,4,4,4,5,4,2,2}, --FIXME + LED = {4,3,4,5,3,4,3,4}, Name = "Линия 1", spec_last = {"last_m",0.5,"things_m"}, spec_last_f = {"last_f",0.5,"things_f"}, @@ -315,7 +315,7 @@ Metrostroi.AddANSPAnnouncer("RIU Boiko + Pyaseckaya",{ to_rechnaya_f = {"subway_announcers/riu/pyaseckaya/crossline/1/to_rechnaya.mp3",3.336893}, },{ { --МАРШРУТ - LED = {5,4,4,4,5,4,2,2}, + LED = {4,3,4,5,3,4,3,4}, Name = "Линия 1", NameEn = "Line 1", spec_last = {"last_m",0.5,"things_m"}, @@ -728,7 +728,8 @@ Metrostroi.AddSarmatUPOAnnouncer("UPO Artur",{ spec_attention_politeness = {"subway_announcers/sarmat_upo/crossline_artur/spec_attention_politeness.mp3",5.614417}, },{ { --МАРШРУТ - LED = {3,4,5,5,5,5,3,2}, + LED = {4,4,4,4,4,4,4,4}, + Name = "Кировская", { 110,"Международная","Mezhdunarodnaya", arr = {nil,"last_mejdunarodnaya"}, diff --git a/lua/metrostroi/maps/crossline_m12.lua b/lua/metrostroi/maps/crossline_m12.lua index a72a58e..0748a89 100644 --- a/lua/metrostroi/maps/crossline_m12.lua +++ b/lua/metrostroi/maps/crossline_m12.lua @@ -699,6 +699,7 @@ Metrostroi.AddSarmatUPOAnnouncer("UPO Artur",{ },{ { --МАРШРУТ LED = {3,4,5,5,5,5,3,2}, + Name = "Кировская", { 909,"Международная","Mezhdunarodnaya", arr = {nil,"last_mejdunarodnaya"}, diff --git a/lua/metrostroi/maps/crossline_r.lua b/lua/metrostroi/maps/crossline_r.lua index 30891e6..0d6d22d 100644 --- a/lua/metrostroi/maps/crossline_r.lua +++ b/lua/metrostroi/maps/crossline_r.lua @@ -781,6 +781,7 @@ Metrostroi.AddSarmatUPOAnnouncer("UPO Artur",{ },{ { --МАРШРУТ LED = {3,4,5,5,5,5,5}, + Name = "Кировская", { 110,"Международная","Mezhdunarodnaya", arr = {nil,"last_mejdunarodnaya"}, diff --git a/lua/metrostroi/maps/loopline.lua b/lua/metrostroi/maps/loopline.lua index f1984f3..993cbb9 100644 --- a/lua/metrostroi/maps/loopline.lua +++ b/lua/metrostroi/maps/loopline.lua @@ -27,13 +27,13 @@ Metrostroi.AddLastStationTex("720",656,"models/metrostroi_schemes/destination_ta Metrostroi.AddPassSchemeTex("717_new","1 Line",{ "models/metrostroi_schemes/mus_loopline", }) -Metrostroi.AddPassSchemeTex("720","Crossline",{ - "metrostroi_skins/81-720_schemes/loopliner", - "metrostroi_skins/81-720_schemes/loopline", +Metrostroi.AddPassSchemeTex("720","Loopline",{ + "metrostroi_skins/81-720_schemes/loop", + "metrostroi_skins/81-720_schemes/loopr", }) -Metrostroi.AddPassSchemeTex("722","Crossline",{ - "metrostroi_skins/81-722_schemes/loopliner", - "metrostroi_skins/81-722_schemes/loopline", +Metrostroi.AddPassSchemeTex("722","Loopline",{ + "metrostroi_skins/81-722_schemes/loop", + "metrostroi_skins/81-722_schemes/loopr", }) Metrostroi.TickerAdverts = { "МЕТРОПОЛИТЕН ИМЕНИ ГАРРИ НЬЮМАНА ПРИГЛАШАЕТ НА РАБОТУ РЕАЛЬНЕ МАФЕНЕСТОВ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,ТЕЛЕФОН ДЛЯ СПРАВОК 8 (800) 555-35-35", @@ -71,8 +71,8 @@ Metrostroi.AddSarmatUPOAnnouncer("UPO RHINO",{ spec_line5= {"subway_announcers/sarmat_upo/rhino/loop/spec_line5.mp3",1.748700}, },{ { - LED = {5,6,5,6,5,5}, - Name = "Line 1", + LED = {6,5,5,6,5,5}, + Name = "Кольцевой", Loop = true, { 651,"Первоапрельская","First april", @@ -251,7 +251,7 @@ Metrostroi.AddANSPAnnouncer("ASNP Boiko + Pyaseckaya",{ to_slavnaya_strana_f = {"subway_announcers/asnp/pyaseckaya/loopline/to_slavnaya_strana.mp3",3.839063}, },{ { - LED = {5,5,5,5,5,5}, + LED = {5,10,5,5,5}, Name = "Line 1", Loop = true, BlockDoors = true, @@ -382,7 +382,7 @@ Metrostroi.AddANSPAnnouncer("RIU Boiko + Pyaseckaya",{ to_slavnaya_strana_f = {"subway_announcers/riu/pyaseckaya/loopline/to_slavnaya_strana.mp3",3.939138}, },{ { - LED = {5,5,5,5,5,5}, + LED = {5,10,5,5,5}, Name = "Line 1", Loop = true, BlockDoors = true, @@ -475,7 +475,7 @@ Metrostroi.SetRRIAnnouncer({ to_slavnaya_strana = {"subway_announcers/rri/boiko/loopline/to_slavnaya_strana.mp3",5.505760}, },{ { - LED = {5,5,5,5,5,5}, + LED = {5,10,5,5,5}, Loop = true, Name = "Line 1", spec_last = {"last"}, diff --git a/lua/metrostroi/maps/orange.lua b/lua/metrostroi/maps/orange.lua index 9384b7f..2b5bbc3 100644 --- a/lua/metrostroi/maps/orange.lua +++ b/lua/metrostroi/maps/orange.lua @@ -220,7 +220,7 @@ Metrostroi.AddSarmatUPOAnnouncer("UPO RHINO", { },{ { LED = {2, 2, 3, 3, 4, 3, 3, 3, 3, 3, 3}, - Name = "Line 1", + Name = "Orange", -- Loop = false, { 462,"Икарус","Ikarus", diff --git a/lua/metrostroi/systems/sys_81_71_announcer.lua b/lua/metrostroi/systems/sys_81_71_announcer.lua index e189a0f..133234d 100644 --- a/lua/metrostroi/systems/sys_81_71_announcer.lua +++ b/lua/metrostroi/systems/sys_81_71_announcer.lua @@ -61,6 +61,7 @@ if SERVER then local train = self.Train.WagonList[i] net.WriteEntity(train) net.WriteString(msg) + net.WriteString(self.AnnTable) net.Broadcast() end end @@ -69,12 +70,14 @@ if SERVER then function TRAIN_SYSTEM:Think() if #self.Schedule > 0 and not self.Playing then for i = 1, #self.Train.WagonList do - self.Train.WagonList[i]:SetNW2Bool("AnnouncerPlaying", true) + local train = self.Train.WagonList[i] + train:SetNW2Bool("AnnouncerPlaying", true) end self.Playing = true elseif #self.Schedule == 0 and self.Playing and not self.AnnounceTimer then for i = 1, #self.Train.WagonList do - self.Train.WagonList[i]:SetNW2Bool("AnnouncerPlaying", false) + local train = self.Train.WagonList[i] + train:SetNW2Bool("AnnouncerPlaying", false) end self.Playing = false end @@ -145,6 +148,7 @@ else local train = net.ReadEntity() if not IsValid(train) or not train.RenderClientEnts then return end local snd = net.ReadString() + train.Announcer.AnnTable = net.ReadString() if train.AnnouncerPositions then for k, v in ipairs(train.AnnouncerPositions) do @@ -155,7 +159,8 @@ else end end) - function TRAIN_SYSTEM:ClientInitialize() + function TRAIN_SYSTEM:ClientInitialize(tbl) + self.AnnTable = tbl end function TRAIN_SYSTEM:ClientThink() diff --git a/lua/metrostroi/systems/sys_81_71_upo.lua b/lua/metrostroi/systems/sys_81_71_upo.lua index 86095f2..9990a98 100644 --- a/lua/metrostroi/systems/sys_81_71_upo.lua +++ b/lua/metrostroi/systems/sys_81_71_upo.lua @@ -44,11 +44,11 @@ end function TRAIN_SYSTEM:Play(dep) local tbl = Metrostroi.UPOSetup if not tbl then return end - self.Train.Announcer:TriggerInput("Reset","AnnouncementsUPO") local stbl = tbl[self.Station] - local path = self.Path and 2 or 1 if not stbl or dep and not stbl.dep or not dep and not stbl.arr and not stbl.arrlast then return end + local path = self.Path and 2 or 1 if dep and stbl.dep and stbl.dep[path] and (not self.Train.OnUPOArrived or self.Train:OnUPOArrived()) then + self.Train.Announcer:TriggerInput("Reset","AnnouncementsUPO") self:AnnQueue(-2) self:AnnQueue{"noise_end","buzz_end_upo"} if self.Buzz then self:AnnQueue{"buzz_start_upo",self.Buzz} else self:AnnQueue("buzz_end_upo") end @@ -68,6 +68,7 @@ function TRAIN_SYSTEM:Play(dep) lastst = true end if msg and (not self.Train.OnUPOArrived or self.Train:OnUPOArrived()) then + self.Train.Announcer:TriggerInput("Reset","AnnouncementsUPO") self:AnnQueue(-2) self:AnnQueue{"noise_end","buzz_end_upo"} if self.Buzz then self:AnnQueue{"buzz_start_upo",self.Buzz} else self:AnnQueue("buzz_end_upo") end diff --git a/lua/metrostroi/systems/sys_81_722_bukp.lua b/lua/metrostroi/systems/sys_81_722_bukp.lua index ba638ec..1ab89e1 100644 --- a/lua/metrostroi/systems/sys_81_722_bukp.lua +++ b/lua/metrostroi/systems/sys_81_722_bukp.lua @@ -72,6 +72,7 @@ function TRAIN_SYSTEM:CStateTarget(name,targetname,targetsys,targetid,value) end function TRAIN_SYSTEM:Think(dT) local Train = self.Train + local Panel = Train.Panel local Electric = Train.Electric local BUKV = Train.BUKV self.Power = Train.SF19.Value*Train.Electric.Power @@ -194,6 +195,7 @@ function TRAIN_SYSTEM:Think(dT) local RR = Train.KRO.Value~=1 if self.Prepared==true and Electric.CabActive>0 and Electric.Emer == 0 then local MFDU = Train.MFDU + local BMCIK = Train.BMCIK local TrainCount = #self.Trains local TrainCHalf = TrainCount/2 if not self.PVU.Sync then @@ -325,7 +327,11 @@ function TRAIN_SYSTEM:Think(dT) else self.PowerCommand = 0 end + self.DoorsClosed = Train.Electric.LSD>0 and self.LSD and (self.DoorsClosed or pos<=0) + if (self.LSD and self.DoorsClosed ~= self.LSD) then + BMCIK:TriggerInput("ClosedDoors") + end MFDU:Error(64,1,Train.Electric.LSD==0 and (pos>0 or MFDU:ErrorGet("64_1"))) --MFDU:Error(64,1,Train.Electric.LSD==0 and self.States.CloseDoors,4) MFDU:Error(5,1,not self.LSD and self.States.CloseDoors and (pos>0 or MFDU:ErrorGet("5_1"))) @@ -338,7 +344,7 @@ function TRAIN_SYSTEM:Think(dT) end if not RR or back or Train.BKCU.Emergency>0 then self.PowerCommand = 0 - elseif self.PowerCommand>0 and (not self.DoorsClosed and Train.VAD.Value==0 or Train.BARS.MOT==0 and Train.RCARS.Value>0 or Train.RCARS.Value==0 and Train.PB.Value==0 and Train.VAH.Value==0 or self.Blocked) --[[or fault]] then + elseif self.PowerCommand>0 and (not self.DoorsClosed and Train.VAD.Value==0 or Train.BARS.MOT==0 and Train.RCARS.Value>0 or Train.RCARS.Value==0 and Train.PB.Value==0 and Train.VAH.Value==0 or self.Blocked) --[[or fault]] then self.PowerCommand = 0 self.Blocked = true else @@ -358,11 +364,18 @@ function TRAIN_SYSTEM:Think(dT) self:CState("Brake",self.PowerCommand < 0 or Command~=nil) self:CState("ARSBrake",Train.BARS.T1 > 0) --Door controls - self.DoorLeft = (RR and Train.DoorSelect.Value==0 and Train.DoorClose.Value==1 and self.Speed<3) and 1 or 0 - self.DoorRight = (RR and Train.DoorSelect.Value==1 and Train.DoorClose.Value==1 and self.Speed<3) and 1 or 0 - MFDU:Error(61,1,(Train.DoorLeft1.Value > 0 or Train.DoorLeft2.Value > 0) and self.DoorLeft == 0 or Train.DoorRight.Value > 0 and self.DoorRight == 0) - self.OpenLeft = not self.States.CloseDoors and (Train.DoorLeft1.Value > 0 or Train.DoorLeft2.Value > 0) and self.DoorLeft > 0 - self.OpenRight = not self.States.CloseDoors and Train.DoorRight.Value > 0 and self.DoorRight > 0 + local allowOpenDoors = RR and Panel.DoorClose==0 and Panel.DoorCloseAVT==0 and self.Speed<3 + self.DoorLeft = (allowOpenDoors and Panel.DoorSelect==0) and 1 or 0 + self.DoorRight = (allowOpenDoors and Panel.DoorSelect==1) and 1 or 0 + MFDU:Error(61,1,(Panel.DoorLeft1 > 0 or Panel.DoorLeft2 > 0) and self.DoorLeft == 0 or Panel.DoorRight > 0 and self.DoorRight == 0) + local openLeft,openRight = self.OpenLeft,self.OpenRight + self.OpenLeft = (Panel.DoorLeft1 > 0 or Panel.DoorLeft2 > 0) and self.DoorLeft > 0 + self.OpenRight = Panel.DoorRight > 0 and self.DoorRight > 0 + + if (self.OpenLeft and openLeft ~= self.OpenLeft) or (self.OpenRight and openRight ~= self.OpenRight) then + BMCIK:TriggerInput("OpenDoors",self.OpenRight and 0x52 or 0x4C) -- 'L', 'R' + end + self:CState("OpenLeft",not self.States.CloseDoors and (self.States.OpenLeft or self.OpenLeft)) self:CState("OpenRight",not self.States.CloseDoors and (self.States.OpenRight or self.OpenRight)) if MFDU:ErrorGet("49_1") and MFDU:ErrorGet("49_1")[4] then @@ -374,12 +387,21 @@ function TRAIN_SYSTEM:Think(dT) else self.BackDoors = nil end - MFDU:Error(49,1,(Train.DoorBack.Value>0 and Train.DoorSelect.Value==1 or MFDU:ErrorGet("49_1") and self.BackDoors~=nil) and not self.States.CloseDoors) + MFDU:Error(49,1,(Panel.DoorBack>0 and Panel.DoorSelect==1 or MFDU:ErrorGet("49_1") and self.BackDoors~=nil) and not self.States.CloseDoors) Train:CANWrite("BUKP",Train:GetWagonNumber(),"BUKV",self.Trains[#self.Trains].ID,"OpenRightBack",self.BackDoors and self.BackDoors~=true) - if self.CloseRing and (Train.DoorLeft1.Value > 0 or Train.DoorLeft2.Value > 0 or Train.DoorRight.Value > 0 or self.LSD) then self.CloseRing = false end - if (not self.CloseRing or self.CloseRing and CurTime()-self.CloseRing<0) and Train.DoorClose.Value==2 and not self.LSD then self.CloseRing = CurTime() end - self:CState("CloseDoors",RR and Train.SF7.Value>0 and (Train.DoorClose.Value == 0 or (not self.CloseRing and Train.DoorClose.Value==2 or self.CloseRing and CurTime()-self.CloseRing>4))) + if self.CloseDoorsDelay then + if self.DoorsClosed or (Panel.DoorCloseAVT==0 and (self.OpenLeft or self.OpenRight)) then + self.CloseDoorsDelay = nil + end + else + if RR and Panel.DoorCloseAVT>0 and not self.DoorsClosed then + self.CloseDoorsDelay = CurTime()+4 + BMCIK:TriggerInput("CloseDoorsAVT") + end + end + + self:CState("CloseDoors",RR and (Panel.DoorClose>0 or self.CloseDoorsDelay and CurTime()>self.CloseDoorsDelay)) self:CState("PassLight",Train.PassLight.Value>0) self:CState("PassVent",Train.PassVent.Value-1) if BARSPower and Train.BARS.V2 > 0 or not BARSPower and math.abs(self.Speed) < 0.5 and self.PowerCommand < 0 then @@ -401,7 +423,6 @@ function TRAIN_SYSTEM:Think(dT) self:CState("PN1",false) self:CState("PN2",false) end - self:CState("CloseRing",self.CloseRing and (CurTime()-self.CloseRing)%1<=0.5) --[[ self:CState("RVPB",(1-Train.RV["KRO5-6"])*Train.SF2.Value > 0) self.ControllerState = stength diff --git a/lua/metrostroi/systems/sys_81_722_bukv.lua b/lua/metrostroi/systems/sys_81_722_bukv.lua index 6fe93e7..c1e52f4 100644 --- a/lua/metrostroi/systems/sys_81_722_bukv.lua +++ b/lua/metrostroi/systems/sys_81_722_bukv.lua @@ -265,11 +265,6 @@ function TRAIN_SYSTEM:Think() else self.Strength = 0 end - local clRing = self:Get("CloseRing") - if self.CloseRing ~= clRing then - self.CloseRing = clRing - if clRing then Train:PlayOnce("door_alarm",1,1) end - end self.DisableLights = self:Get("PVU2") and 1 or 0 self.EnableLights = self:Get("PassLight") and 1 or 0 self.DisablePSN = self:Get("PVU3") and 1 or 0 diff --git a/lua/metrostroi/systems/sys_81_722_electric.lua b/lua/metrostroi/systems/sys_81_722_electric.lua index 12d3ac7..aaf23e3 100644 --- a/lua/metrostroi/systems/sys_81_722_electric.lua +++ b/lua/metrostroi/systems/sys_81_722_electric.lua @@ -169,10 +169,16 @@ function TRAIN_SYSTEM:Think(dT) Train:WriteTrainWire(24,BTB*S["NEmergencyBrake"]) Train:WriteTrainWire(25,BTB*self.BTB*(self.KTR==3 and 0 or 1)) - Train:WriteTrainWire(37,(S["RU"]+Train.BUKP.DoorRight)*Train.SF7.Value*Train.DoorRight.Value) - Train:WriteTrainWire(38,(S["RU"]+Train.BUKP.DoorLeft)*Train.SF7.Value*(Train.DoorLeft1.Value+Train.DoorLeft2.Value)) - Train:WriteTrainWire(39,S["RU"]*Train.SF7.Value*C(Train.DoorClose.Value==0)) - + Panel.DoorLeft1 = Train.DoorLeft1.Value*Train.SF7.Value + Panel.DoorLeft2 = Train.DoorLeft2.Value*Train.SF7.Value + Panel.DoorRight = Train.DoorRight.Value*Train.SF7.Value + Panel.DoorClose = C(Train.DoorClose.Value==0)*Train.SF7.Value + Panel.DoorCloseAVT = C(Train.DoorClose.Value==2)*Train.SF7.Value + Panel.DoorSelect = Train.DoorSelect.Value*Train.SF7.Value + Panel.DoorBack = Train.DoorBack.Value*Train.SF7.Value + Train:WriteTrainWire(37,(S["RU"]+Train.BUKP.DoorRight)*Panel.DoorRight) + Train:WriteTrainWire(38,(S["RU"]+Train.BUKP.DoorLeft)*(Panel.DoorLeft1+Panel.DoorLeft2)) + Train:WriteTrainWire(39,S["RU"]*C(Panel.DoorClose==0)*C(Panel.DoorCloseAVT==0)) Panel.BattOn = BO Panel.BattOff = BO*Train.BatteryOff.Value @@ -192,9 +198,8 @@ function TRAIN_SYSTEM:Think(dT) Panel.ARSPower = Panel.BARSPower*(1-Train.BUKP.Back)*Train.ARS.Value Panel.ALSPower = BO*(1-Train.BUKP.Back)*Train.ALS.Value - Panel.UPOPower = BO*S["RV"]*Train.R_UPO.Value - Train:WriteTrainWire(15,BO*(Train.UPO.LineOut*Train.SarmatUPO.UPOActive+Train.SarmatUPO.LineOut)) - --print(W[15],Train.UPO.LineOut*Train.SarmatUPO.UPOActive,Train.SarmatUPO.LineOut) + Panel.UPOPower = BO*S["RV"]*Train.BMCIK.UPOActive + Train:WriteTrainWire(15,BO*(Train.BMCIK.LineOut + Train.UPO.LineOut)) self.Emer = S["RU"] end diff --git a/lua/metrostroi/systems/sys_81_722_panel.lua b/lua/metrostroi/systems/sys_81_722_panel.lua index 05c9378..beabbfb 100644 --- a/lua/metrostroi/systems/sys_81_722_panel.lua +++ b/lua/metrostroi/systems/sys_81_722_panel.lua @@ -17,7 +17,7 @@ function TRAIN_SYSTEM:Initialize() self.Train:LoadSystem("SF7","Relay","Switch",{normally_closed = true,bass=true}) self.Train:LoadSystem("SF8","Relay","Switch",{normally_closed = true,bass=true}) self.Train:LoadSystem("SF9","Relay","Switch",{normally_closed = true,bass=true}) - self.Train:LoadSystem("R_UPO","Relay","Switch",{normally_closed = true,bass=true}) + self.Train:LoadSystem("SF00","Relay","Switch",{bass=true}) self.Train:LoadSystem("SF01","Relay","Switch",{bass=true}) self.Train:LoadSystem("SF10","Relay","Switch",{bass=true}) self.Train:LoadSystem("SF11","Relay","Switch",{bass=true}) @@ -135,9 +135,13 @@ function TRAIN_SYSTEM:Initialize() self.EmergencyDriveL = 0 self.EmergencyBrakeTPlusL = 0 - self.DoorLeftL = 0 - self.DoorRightL = 0 - self.MFDUPowerL = 0 + self.DoorLeft1 = 0 + self.DoorLeft2 = 0 + self.DoorRight = 0 + self.DoorClose = 0 + self.DoorCloseAVT = 0 + self.DoorSelect = 0 + self.DoorBack = 0 self.CabLights = 0 self.PanelLights = 0 @@ -177,7 +181,7 @@ function TRAIN_SYSTEM:Inputs() end function TRAIN_SYSTEM:Outputs() - return { "Controller","BattOn","BattOff","SOSDL","RS","AVS","LRU","EmergencyDriveL","EmergencyBrakeTPlusL","DoorLeftL","DoorRightL","MFDUPowerL","CabLights","PanelLights","Headlights1","Headlights2","RedLights","EmergencyLights","MainLights", "V4","SOSD","UPOPower","AnnouncerPlaying", "PassSchemePowerL", "PassSchemePowerR","DoorsW","BrW","GRP","RC","VPR1","VPR2","BARSPower","ARSPower","ALSPower"} + return { "Controller","BattOn","BattOff","SOSDL","RS","AVS","LRU","EmergencyDriveL","EmergencyBrakeTPlusL","DoorLeft1","DoorLeft2","DoorRight","DoorClose","DoorCloseAVT","DoorSelect","DoorBack","CabLights","PanelLights","Headlights1","Headlights2","RedLights","EmergencyLights","MainLights", "V4","SOSD","UPOPower","AnnouncerPlaying", "PassSchemePowerL", "PassSchemePowerR","DoorsW","BrW","GRP","RC","VPR1","VPR2","BARSPower","ARSPower","ALSPower"} end --if not TURBOSTROI then return end function TRAIN_SYSTEM:TriggerInput(name,value) diff --git a/lua/metrostroi/systems/sys_81_722_passscheme.lua b/lua/metrostroi/systems/sys_81_722_passscheme.lua index 2e836b8..3f7861b 100644 --- a/lua/metrostroi/systems/sys_81_722_passscheme.lua +++ b/lua/metrostroi/systems/sys_81_722_passscheme.lua @@ -1,37 +1,178 @@ -------------------------------------------------------------------------------- --- 81-722 pass schemes +-- 81-722 BNT-12 system -------------------------------------------------------------------------------- -- Copyright (C) 2013-2018 Metrostroi Team & FoxWorks Aerospace s.r.o. -- Contains proprietary code. See license.txt for additional information. -------------------------------------------------------------------------------- -Metrostroi.DefineSystem("81_722_PassScheme") +Metrostroi.DefineSystem("81_722_BNT") TRAIN_SYSTEM.DontAccelerateSimulation = true +TRAIN_SYSTEM.CAN_ACTIVATE = 0x01 +TRAIN_SYSTEM.CAN_BMTS_TEXT = 0x10 +TRAIN_SYSTEM.CAN_CURR = 0x21 +TRAIN_SYSTEM.CAN_NEXT = 0x22 +TRAIN_SYSTEM.CAN_PATH = 0x23 +TRAIN_SYSTEM.CAN_CLOSERING = 0x24 +TRAIN_SYSTEM.CAN_VOLUMES = 0x25 +TRAIN_SYSTEM.CAN_SPEED = 0x26 + +-- self.AnnouncerPositions[4]: +-- 0x43 - Cabin speaker +-- 0x4C - Left side +-- 0x52 - Right side function TRAIN_SYSTEM:Initialize() + self.Volumes = { + Speed = 0, + Ann = 5, + UPO = 5, + V5 = 0 + } + self.Left = { + Power = false, + CloseRing = false, + CloseRingState = false, + Init = false, + Curr = 0, + Next = 0, + Back = false + } + self.Right = { + Power = false, + CloseRing = false, + CloseRingState = false, + Init = false, + Curr = 0, + Next = 0, + Back = false + } end if TURBOSTROI then return end -function TRAIN_SYSTEM:Initialize() - self.PassSchemeCurr = -1 - self.PassSchemeNext = 0 - self.PassSchemePath = false -end function TRAIN_SYSTEM:CANReceive(source,sourceid,target,targetid,textdata,numdata) - if textdata == "Current" then self.Curr = numdata end - if textdata == "Arrival" then self.Next = numdata end - if textdata == "Path" then self.Path = numdata end -end -function TRAIN_SYSTEM:Think() - local Train = self.Train - if Train.Panel.PassSchemePowerL>0 and Train.Panel.PassSchemePowerR>0 then - self.PassSchemeCurr = self.Curr or -1 - self.PassSchemeNext = self.Next or 0 - self.PassSchemePath = self.Path--not Train.BUV.RevOrientation and self.Path or Train.BUV.RevOrientation and not self.Path - --if self.RevOrientation then self.PassSchemePath = not self.PassSchemePath end - else - self.PassSchemeCurr = 0 - self.PassSchemeNext = 0 - self.PassSchemePath = false + if textdata == self.CAN_SPEED then + self.Volumes.Speed = numdata + return + end + if textdata == self.CAN_CURR then + self.Left.Init = true + self.Right.Init = true + self.Left.Curr = self.Left.Power and numdata or 0 + self.Right.Curr = self.Right.Power and numdata or 0 + end + if textdata == self.CAN_NEXT then + self.Left.Init = true + self.Right.Init = true + self.Left.Next = self.Left.Power and numdata or 0 + self.Right.Next = self.Right.Power and numdata or 0 + end + if textdata == self.CAN_PATH then + self.Left.Init = true + self.Right.Init = true + self.Left.Back = self.Left.Power and numdata or false + self.Right.Back = self.Right.Power and numdata or false + end + if textdata == self.CAN_CLOSERING then + self.Left.CloseRing = self.Left.Power and numdata or false + self.Right.CloseRing = self.Right.Power and numdata or false + end + if textdata == self.CAN_VOLUMES then + self.Volumes.Ann = numdata[1] + self.Volumes.UPO = numdata[2] + self.Volumes.V5 = numdata[3] + end + if textdata == self.CAN_ACTIVATE then + for k,v in ipairs(self.Train.AnnouncerPositions) do + if (v[4] == 0x4C and self.Left.Power) or (v[4] == 0x52 and self.Right.Power) then + self.Train:PlayOnce("announcer_sarmat_start"..k,nil,self.Volumes.Ann/10,1) + end + end end end + +local function setBitValue(targetVar, value, offset, bitCount) + value = bit.band(value,bit.lshift(1,bitCount)-1) + return bit.bor(targetVar,bit.lshift(value,offset)) +end + +function TRAIN_SYSTEM:Think() + local Train = self.Train + self.BNT(self.Left,self.Train.Panel.PassSchemePowerL > 0) + self.BNT(self.Right,self.Train.Panel.PassSchemePowerR > 0) + + local doorAlarm = 0 + doorAlarm = setBitValue(doorAlarm,self.Left.CloseRing and 1 or self.Right.CloseRing and 1 or 0,0,1) + doorAlarm = setBitValue(doorAlarm,self.Left.CloseRingState and 1 or 0,1,1) + doorAlarm = setBitValue(doorAlarm,self.Right.CloseRingState and 1 or 0,2,1) + Train:SetNW2Int("BNT:DoorAlarm",doorAlarm) + + local volumes = 0 + local volAnn = self.Volumes.Ann + local volUPO = self.Volumes.UPO + if self.Volumes.Speed > 5 then + volAnn = math.min(10,self.Volumes.Ann + self.Volumes.V5) + volUPO = math.min(10,self.Volumes.UPO + self.Volumes.V5) + end + volumes = setBitValue(volumes,volAnn,0,4) + volumes = setBitValue(volumes,volUPO,4,4) + Train:SetNW2Int("BNT:Volumes",volumes) + + local statesLeft,statesRight = 0,0 + statesLeft = setBitValue(statesLeft,self.Left.Power and 1 or 0,0,1) + statesLeft = setBitValue(statesLeft,self.Left.Init and 1 or 0,1,1) + statesLeft = setBitValue(statesLeft,self.Left.Back and 1 or 0,2,1) + statesLeft = setBitValue(statesLeft,self.Left.Next, 3,6) + statesLeft = setBitValue(statesLeft,self.Left.Curr, 9,6) + + statesRight = setBitValue(statesRight,self.Right.Power and 1 or 0,0,1) + statesRight = setBitValue(statesRight,self.Right.Init and 1 or 0,1,1) + statesRight = setBitValue(statesRight,self.Right.Back and 1 or 0,2,1) + statesRight = setBitValue(statesRight,self.Right.Next, 3,6) + statesRight = setBitValue(statesRight,self.Right.Curr, 9,6) + + Train:SetNW2Int("BNT:Left",statesLeft) + Train:SetNW2Int("BNT:Right",statesRight) +end + +function TRAIN_SYSTEM:BNT(Power) + if Power and not self.Power then + self.Power = true + end + if not Power and self.Power then + self.Power = false + self.CloseRing = false + self.CloseRingState = false + self.CloseRingTimer = nil + self.CurrTimer = nil + self.Init = false + self.Curr = 0 + self.Next = 0 + self.Back = false + end + + if not self.Power then return end + + if self.CloseRing then + if not self.CloseRingTimer then self.CloseRingTimer = CurTime() end + self.CloseRingState = (CurTime() - self.CloseRingTimer)%1<0.5 + if CurTime() - self.CloseRingTimer > 30 then + self.CloseRing = false + end + else + if self.CloseRingTimer then + self.CloseRingTimer = nil + self.CloseRingState = false + end + end + + if not self.Init then + if not self.CurrTimer then self.CurrTimer = CurTime() end + if CurTime() - self.CurrTimer > 0.5 then + self.Curr = self.Curr + 1 + if self.Curr > 32 then self.Curr = 0 end + self.CurrTimer = CurTime() + end + else + if self.CurrTimer then self.CurrTimer = nil end + end +end \ No newline at end of file diff --git a/lua/metrostroi/systems/sys_81_722_pneumatic.lua b/lua/metrostroi/systems/sys_81_722_pneumatic.lua index 11a6c3b..8dcc6ff 100644 --- a/lua/metrostroi/systems/sys_81_722_pneumatic.lua +++ b/lua/metrostroi/systems/sys_81_722_pneumatic.lua @@ -526,9 +526,19 @@ function TRAIN_SYSTEM:Think(dT) self.DoorLeft = false self.DoorRight = false end--]] - local commandLeft = (Train:ReadTrainWire(34) > 0 or Train.BUKV.OpenLeft) and (Train:ReadTrainWire(38) > 0 or Train:ReadTrainWire(39) > 0) and Train.SF41.Value > 0 - local commandRight = (Train.BUKV.OpenRightBack or (Train:ReadTrainWire(34) > 0 or Train.BUKV.OpenRight) and (Train:ReadTrainWire(37) > 0 or Train:ReadTrainWire(39) > 0)) and Train.SF42.Value > 0 - local commandClose = Train.BUKV.CloseDoors and Train.SF43.Value > 0 + local commandLeft,commandRight,commandClose + if Train:ReadTrainWire(34) > 0 then + commandLeft = Train:ReadTrainWire(38) > 0 + commandRight = Train:ReadTrainWire(37) > 0 + commandClose = Train:ReadTrainWire(39) < 1 + else + commandLeft = Train.BUKV.OpenLeft + commandRight = Train.BUKV.OpenRight or Train.BUKV.OpenRightBack + commandClose = Train.BUKV.CloseDoors + end + commandLeft = commandLeft and Train.SF41.Value > 0 + commandRight = commandRight and Train.SF42.Value > 0 + commandClose = commandClose and Train.SF43.Value > 0 if commandClose or commandLeft and commandRight then self.DoorLeft = false self.DoorRight = false diff --git a/lua/metrostroi/systems/sys_81_722_routenumber.lua b/lua/metrostroi/systems/sys_81_722_routenumber.lua index 63ab6d0..df72fdd 100644 --- a/lua/metrostroi/systems/sys_81_722_routenumber.lua +++ b/lua/metrostroi/systems/sys_81_722_routenumber.lua @@ -1,10 +1,10 @@ -------------------------------------------------------------------------------- --- 81-722 route number +-- 81-722 TNM-01 system -------------------------------------------------------------------------------- -- Copyright (C) 2013-2018 Metrostroi Team & FoxWorks Aerospace s.r.o. -- Contains proprietary code. See license.txt for additional information. -------------------------------------------------------------------------------- -Metrostroi.DefineSystem("81_722_RouteNumber") +Metrostroi.DefineSystem("81_722_TNM") TRAIN_SYSTEM.DontAccelerateSimulation = true function TRAIN_SYSTEM:Initialize() @@ -21,211 +21,229 @@ function TRAIN_SYSTEM:Initialize() if self.Train[v] then self.Triggers[v] = self.Train[v].Value > 0.5 end end + self.State = 0 + self.Brightness = 100 + self.BrightKeys = 0 + self.NumberState = 42 if not TURBOSTROI then - self.RouteNumber = IsValid(self.Train.Owner) and Format("%03d",tonumber(self.Train.Owner:GetInfo("metrostroi_route_number","61")) or 0) or "000" - self.CurrentRouteNumber = self.RouteNumber - self.RouteNumberState = 42 + self.Number = IsValid(self.Train.Owner) and tonumber(self.Train.Owner:GetInfo("metrostroi_route_number","61")) or 777 end end - -function TRAIN_SYSTEM:Outputs() - return {} -end - -function TRAIN_SYSTEM:Inputs() - return {} -end if TURBOSTROI then return end -function TRAIN_SYSTEM:TriggerInput(name,value) +function TRAIN_SYSTEM:Trigger(name,value) + if value then + if self.State == 1 then + if name == "RouteNumber1" then self.BrightKeys = self.BrightKeys + 1 end + if name == "RouteNumber3" then self.BrightKeys = self.BrightKeys + 1 end + elseif self.State == 2 then + if name == "RouteNumber1" then + self.BrightKeys = self.BrightKeys + 1 + elseif name == "RouteNumber3" then + self.BrightKeys = self.BrightKeys + 1 + end + end + else + if self.State == 1 then + if not self.NewNumber then self.NewNumber = self.Number end + local rNum = self.NewNumber + local rNum1,rNum2,rNum3 = math.floor(rNum/100)%10,math.floor(rNum/10)%10,math.floor(rNum)%10 + if name == "RouteNumber1" then + self.BrightKeys = math.max(0,self.BrightKeys-1) + if self.BrightKeys < 1 and not self.KeysLock then + rNum1 = rNum1 + 1 + if rNum1 > 9 then rNum1 = 0 end + end + elseif name == "RouteNumber2" then + if self.BrightKeys < 1 and not self.KeysLock then + rNum2 = rNum2 + 1 + if rNum2 > 9 then rNum2 = 0 end + end + elseif name == "RouteNumber3" then + self.BrightKeys = math.max(0,self.BrightKeys-1) + if self.BrightKeys < 1 and not self.KeysLock then + rNum3 = rNum3 + 1 + if rNum3 > 9 then rNum3 = 0 end + end + end + self.NewNumber = rNum1*100+rNum2*10+rNum3 + if self.NewNumber ~= self.Number then self.NewNumberTimer = CurTime()+5 end + elseif self.State == 2 then + local bright = self.Brightness + local bright1,bright2,bright3 = math.floor(bright/100)%10,math.floor(bright/10)%10,math.floor(bright)%10 + if name == "RouteNumber1" then + self.BrightKeys = math.max(0,self.BrightKeys-1) + if self.BrightKeys < 1 and not self.KeysLock then + bright1 = bright1 + 1 + if bright1 > 1 then bright1 = 0 end + end + elseif name == "RouteNumber2" then + if self.BrightKeys < 1 and not self.KeysLock then + bright2 = bright2 + 1 + if bright2 > 9 then bright2 = 0 end + end + elseif name == "RouteNumber3" then + self.BrightKeys = math.max(0,self.BrightKeys-1) + if self.BrightKeys < 1 and not self.KeysLock then + bright3 = bright3 + 1 + if bright3 > 9 then bright3 = 0 end + end + end + self.Brightness = math.min(100,bright1*100+bright2*10+bright3) + end + if self.KeysLock and self.BrightKeys == 0 then self.KeysLock = false end + end end if SERVER then - function TRAIN_SYSTEM:Trigger(name,value) - local Train = self.Train - if value then - if not self.NextRouteNumberTimer then - self.NextRouteNumber = Format("%03d",self.CurrentRouteNumber) - end - self.NextRouteNumberTimer = CurTime() - end - if name == "RouteNumber1" and value then - local num = tonumber(self.NextRouteNumber[1]+1) - if num > 9 then num = 0 end - self.NextRouteNumber = self.NextRouteNumber:SetChar(1,num) - end - if name == "RouteNumber2" and value then - local num = tonumber(self.NextRouteNumber[2]+1) - if num > 9 then num = 0 end - self.NextRouteNumber = self.NextRouteNumber:SetChar(2,num) - end - if name == "RouteNumber3" and value then - local num = tonumber(self.NextRouteNumber[3]+1) - if num > 9 then num = 0 end - self.NextRouteNumber = self.NextRouteNumber:SetChar(3,num) - end - end function TRAIN_SYSTEM:Think(dT) local Train = self.Train - local Panel = Train.Panel - local Work = Train.Electric.Power --and Train.SF19.Value > 0 - if Work then + local Power = Train.Electric.Power > 0 + if Power then for k,v in pairs(self.TriggerNames) do if Train[v] and (Train[v].Value > 0.5) ~= self.Triggers[v] then self:Trigger(v,Train[v].Value > 0.5) self.Triggers[v] = Train[v].Value > 0.5 end end - if self.NextRouteNumberTimer and CurTime()-self.NextRouteNumberTimer > 5 and self.RouteNumberState == 42 then - self.NextRouteNumberTimer = nil - self.CurrentRouteNumber = tonumber(self.NextRouteNumber) + if self.State == 1 then + if self.BrightKeys > 1 then + if not self.BrightTimer then self.BrightTimer = CurTime()+1 end + if CurTime() > self.BrightTimer then self.State=2 self.BrightTimer=nil self.KeysLock = true end + else + if self.BrightTimer then self.BrightTimer = nil end + end + Train:SetNW2Int("TNM:Number",self.NewNumber or self.Number) + elseif self.State == 0 then + self.State = 1 + elseif self.State == 2 then + if self.BrightKeys > 1 and not self.KeysLock then + self.State = 1 + self.KeysLock = true + end + Train:SetNW2Int("TNM:Number",self.Brightness) end - if not self.RouteNumberUpdateDelay or self.RouteNumberUpdateDelay and CurTime()-self.RouteNumberUpdateDelay > 0.1 then - if self.RouteNumberState >= 0 and self.RouteNumber ~= self.CurrentRouteNumber then - self.RouteNumberState = self.RouteNumberState-1 - Train:PlayOnce("blinker_off"..(self.RouteNumberState%2+1),"bass",0.6+math.random()*0.3,1) + if self.State > 0 then + if self.NewNumberTimer and CurTime()>self.NewNumberTimer then + if not self.NumberUpdate then self.NumberUpdate = CurTime()+0.1 end + self.NewNumberTimer = nil end - if self.RouteNumberState < 42 and self.RouteNumber == self.CurrentRouteNumber then - self.RouteNumberState = self.RouteNumberState+1 - Train:PlayOnce("blinker_on"..(self.RouteNumberState%2+1),"bass",0.6+math.random()*0.3,1) + if self.NumberUpdate and CurTime() > self.NumberUpdate then + self.NumberUpdate = CurTime()+0.1 + if self.Number ~= self.NewNumber then + self.NumberState = math.max(0,self.NumberState - 1) + Train:PlayOnce("blinker_off"..(self.NumberState%2+1),"bass",0.6+math.random()*0.3,1) + if self.NumberState == 0 then self.Number = self.NewNumber end + elseif self.Number == self.NewNumber then + self.NumberState = math.min(42,self.NumberState + 1) + Train:PlayOnce("blinker_on"..(self.NumberState%2+1),"bass",0.6+math.random()*0.3,1) + if self.NumberState == 42 then self.NewNumber = nil self.NumberUpdate = nil end + end end - if self.RouteNumberState < 0 and self.RouteNumber ~= self.CurrentRouteNumber then - self.RouteNumber = self.CurrentRouteNumber - self.RouteNumberState = self.RouteNumberState+1 - Train:PlayOnce("blinker_on"..(self.RouteNumberState%2+1),"bass",0.6+math.random()*0.3,1) - end - self.RouteNumberUpdateDelay = CurTime() + Train:SetNW2Int("TNM:Number2",self.Number) + end + Train:SetNW2Int("TNM:NumberState",self.NumberState) + Train:SetNW2Int("TNM:Bright",self.NumberUpdate and 0 or self.Brightness) + else + if self.State ~= 0 then + self.BrightTimer = nil + self.NewNumber = nil + self.NewNumberTimer = nil + self.NumberUpdate = nil + self.State = 0 end end - - Train:SetNW2Bool("RouteNumberWork",Work) - Train:SetNW2Int("RouteNumberBright",10) - Train:SetNW2Int("RouteNumberState",self.RouteNumberState) - Train:SetNW2String("RouteNumberLastStation",Train.SarmatUPO.LastStationName) - Train:SetNW2Bool("RouteNumberLastStationWork",Work and Train.SF18.Value > 0 and Train.SarmatUPO.SarmatState > 0) - Train:SetNW2Int("RouteNumber",self.RouteNumber) - Train:SetNW2Int("RouteNumberSet",self.NextRouteNumber or self.RouteNumber) + + Train:SetNW2Int("TNM:State",self.State) end -else +else + local TNMPixels = surface.GetTextureID("models/metrostroi_train/81-722/screens/sarmat_upo/tnm") + function TRAIN_SYSTEM:ClientInitialize() - self.CurrentRouteNumber = 0 - self.RouteNumberState = 42 - self.RouteNumberNeedUpdate = true - self.Work = false - self.RouteNumberBright = 0 + self.Brightness = 100 + self.NumberState = 42 + self.Number = 61 + self.NeedUpdate = true end - function TRAIN_SYSTEM:ClientThink() - if self.Train:ShouldDrawPanel("RouteNumber") and self.RouteNumberNeedUpdate then - render.PushRenderTarget(self.Train.RouteNumber,0,0,256, 128) + + function TRAIN_SYSTEM:ClientThink(dT) + -- ТНМ-1.02 АВДБ.687240.049-10 + local Train = self.Train + local bright = (4.5-(Train:GetNW2Int("TNM:Bright",1)/100)*math.min(1,Train:GetNW2Int("TNM:State",0))*3.5) + local number = Train:GetNW2Int("TNM:Number2",777) + local rnState = Train:GetNW2Int("TNM:NumberState",42) + if self.Brightness ~= bright then + self.Brightness = bright + self.NeedUpdate = true + end + if self.NumberState ~= rnState then + self.NumberState = rnState + self.NeedUpdate = true + end + if self.Number ~= number then + self.Number = number + self.NeedUpdate = true + end + -- self.NeedUpdate = true + if self.NeedUpdate then + render.PushRenderTarget(Train.TNMScr,0,0,256,128) render.Clear(0, 0, 0, 0) cam.Start2D() - surface.SetDrawColor(0,0,0) - --surface.DrawRect(0,0,54,32) - self:RouteNumber(self.Train) + self:TNM(Train) cam.End2D() render.PopRenderTarget() - self.RouteNumberNeedUpdate = false - end - if self.LastStationNeedUpdate then - render.PushRenderTarget(self.Train.LastStation,0,0,512, 64) - render.Clear(0, 0, 0, 0) - cam.Start2D() - surface.SetDrawColor(0,0,0) - --surface.DrawRect(0,0,54,32) - self:LastStation(self.Train) - cam.End2D() - render.PopRenderTarget() - self.LastStationNeedUpdate = false - end - local number = self.Train:GetNW2Int("RouteNumber",0) - local work = self.Train:GetNW2Bool("RouteNumberWork",false) - if not work and self.CurrentRouteNumber == number then - if work ~= self.Work then - self.RouteNumberBright = 0 - self.Work = false - self.RouteNumberNeedUpdate = true - end - else - local state = self.Train:GetNW2Int("RouteNumberState",0) - local bright = self.Train:GetNW2Int("RouteNumberBright",0) - if self.RouteNumberState ~= state or self.CurrentRouteNumber ~= number or work ~= self.Work or bright ~= self.RouteNumberBright then - self.RouteNumberNeedUpdate = true - self.Work = work - self.RouteNumberBright = bright - self.RouteNumberState = state - self.CurrentRouteNumber = number - end - end - local lswork = self.Train:GetNW2Bool("RouteNumberLastStationWork") - if not lswork then - if lswork ~= self.LastStationWork then - self.LastStationWork = false - self.LastStationNeedUpdate = true - end - else - local laststation = self.Train:GetNW2String("RouteNumberLastStation","") - if self.LastStationName ~= laststation or self.LastStationWork ~= lswork then - self.LastStationWork = lswork - self.LastStationName = laststation - self.LastStationNeedUpdate = true - end + self.NeedUpdate = false end end local numbers = { - ["0"] = {"0111110","1111111","1100011","1100011","1100011","1100011","1100011","1100011","1100011","1100011","1100011","1100011","1111111","0111110",}, - ["1"] = {"0001100","0011100","0111100","0001100","0001100","0001100","0001100","0001100","0001100","0001100","0001100","0001100","0111111","0111111",}, - ["2"] = {"0222220","2222222","2200022","0000022","0000022","0000022","0000220","0002200","0022000","0220000","2200000","2200000","2222222","2222222",}, - ["3"] = {"0333330","3333333","3300033","0000033","0000033","0000033","0033330","0033330","0000033","0000033","0000033","3300033","3333333","0333330",}, - ["4"] = {"4400044","4400044","4400044","4400044","4400044","4400044","4400044","4444444","4444444","0000044","0000044","0000044","0000044","0000044",}, - ["5"] = {"5555555","5555555","5500000","5500000","5500000","5500000","5555550","5555555","0000055","0000055","0000055","5500055","5555555","0555550",}, - ["6"] = {"0666660","6666666","6600066","6600000","6600000","6600000","6666660","6666666","6600066","6600066","6600066","6600066","6666666","0666660",}, - ["7"] = {"7777777","7777777","7700077","0000077","0000770","0007700","0077000","0770000","7700000","7700000","7700000","7700000","7700000","7700000",}, - ["8"] = {"0888880","8888888","8800088","8800088","8800088","8800088","0888880","0888888","8800088","8800088","8800088","8800088","8888888","0888880",}, - ["9"] = {"0999990","9999999","9900099","9900099","9900099","9900099","9999999","0999999","0000099","0000099","0000099","9900099","9999999","0999990",}, + [0] = {0x3E,0x7F,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x7F,0x3E}, + [1] = {0x0C,0x1C,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3F,0x3F}, + [2] = {0x3E,0x7F,0x63,0x03,0x03,0x03,0x06,0x0C,0x18,0x30,0x60,0x60,0x7F,0x7F}, + [3] = {0x3E,0x7F,0x63,0x03,0x03,0x03,0x1E,0x1E,0x03,0x03,0x03,0x63,0x7F,0x3E}, + [4] = {0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x7F,0x7F,0x03,0x03,0x03,0x03,0x03}, + [5] = {0x7F,0x7F,0x60,0x60,0x60,0x60,0x7E,0x7F,0x03,0x03,0x03,0x63,0x7F,0x3E}, + [6] = {0x3E,0x7F,0x63,0x60,0x60,0x60,0x7E,0x7F,0x63,0x63,0x63,0x63,0x7F,0x3E}, + [7] = {0x7F,0x7F,0x63,0x03,0x03,0x06,0x0C,0x18,0x30,0x60,0x60,0x60,0x60,0x60}, + [8] = {0x3E,0x7F,0x63,0x63,0x63,0x63,0x3E,0x3E,0x63,0x63,0x63,0x63,0x7F,0x3E}, + [9] = {0x3E,0x7F,0x63,0x63,0x63,0x63,0x7F,0x3F,0x03,0x03,0x03,0x63,0x7F,0x3E}, } - TRAIN_SYSTEM.RouteNumberFont = {} - for i,num in pairs(numbers) do - if not TRAIN_SYSTEM.RouteNumberFont[i] then TRAIN_SYSTEM.RouteNumberFont[i] = {} end - local numtbl = TRAIN_SYSTEM.RouteNumberFont[i] - for ir,row in pairs(num) do - if not numtbl[ir] then numtbl[ir] = {} end - local rowtbl = numtbl[ir] - for ic=1,#row do - rowtbl[ic] = (row[ic] ~= "0") + TRAIN_SYSTEM.TNMFont = {} + for i=0,9 do + TRAIN_SYSTEM.TNMFont[i] = {} + for iy=0,13 do + TRAIN_SYSTEM.TNMFont[i][iy] = {} + for ix=0,6 do + TRAIN_SYSTEM.TNMFont[i][iy][ix] = bit.band(bit.rshift(numbers[i][iy+1],6-ix),1) > 0 end end end - function TRAIN_SYSTEM:LastStation(Train) - if self.LastStationWork then - draw.SimpleText(self.LastStationName,"Metrostroi_722LastStation",256, 24,Color(255,100,60),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - end - end - function TRAIN_SYSTEM:RouteNumber(Train) - local bright = (5-self.RouteNumberBright*0.4) - if self.RouteNumberState < 42 or not self.Work then bright = 5 end - surface.SetDrawColor(150,255,50,255) - surface.SetDrawColor(150/bright,255/bright,50/bright,255) - --surface.SetDrawColor(150,220,50,255) - local num = Format("%03d",self.CurrentRouteNumber) - --print(self.RouteNumberState,math.ceil(self.RouteNumberState/2),self.CurrentRouteNumber,num,type(num),bright) - local rnstate = math.ceil(self.RouteNumberState/2)*2 - local rnstate2 = math.floor(self.RouteNumberState/2)*2 - local half = self.RouteNumberState ~= rnstate - for i=1,3 do - local rnstate = math.ceil((self.RouteNumberState-(i-1)*14)/2)*2 - local rnstate2 = math.floor((self.RouteNumberState-(i-1)*14)/2)*2 - local number = self.RouteNumberFont[num[i]] - if number then - --print(number) - for x=0,6 do - for y=0,13 do - if number[y+1][x+1] and ((14-rnstate2) <= y or ((14-rnstate) <= y and (x%2 > 0 and y%2 == 0 or x%2 == 0 and y%2 > 0))) then - surface.DrawRect((i-1)*64+x*8,1+y*8,7,7) - end + function TRAIN_SYSTEM:TNM(Train) + local rNum = self.Number + local bright = self.Brightness + local tnmState = self.NumberState + + for i=0,2 do + local rnstate = math.ceil((tnmState-i*14)/2)*2 + local rnstate2 = math.floor((tnmState-i*14)/2)*2 + local rNum = math.floor(rNum/10^(2-i))%10 + for ix=0,6 do + for iy=0,13 do + if self.TNMFont[rNum][iy][ix] and ((14-rnstate2) <= iy or ((14-rnstate) <= iy and (ix%2 > 0 and iy%2 == 0 or ix%2 == 0 and iy%2 > 0))) then + surface.SetDrawColor(150/bright,255/bright,50/bright) + else + surface.SetDrawColor(0,0,0,120) end + surface.DrawRect(2+ix*8+i*72,2+iy*8,7,7) end end end + + -- Pixels mask + render.OverrideBlend(true,BLEND_ZERO,BLEND_ONE,BLENDFUNC_MIN) + surface.SetDrawColor(255,255,255) + surface.SetTexture(TNMPixels) + surface.DrawTexturedRectRotated(130,66,256,128,0) + render.OverrideBlend(false) end end diff --git a/lua/metrostroi/systems/sys_81_722_sarmat_upo.lua b/lua/metrostroi/systems/sys_81_722_sarmat_upo.lua index 30b5357..ddd682b 100644 --- a/lua/metrostroi/systems/sys_81_722_sarmat_upo.lua +++ b/lua/metrostroi/systems/sys_81_722_sarmat_upo.lua @@ -1,58 +1,95 @@ -------------------------------------------------------------------------------- --- 81-722 "Sarmat-UPO" announcer system +-- 81-722 BMCIK-01 system -------------------------------------------------------------------------------- -- Copyright (C) 2013-2018 Metrostroi Team & FoxWorks Aerospace s.r.o. -- Contains proprietary code. See license.txt for additional information. -------------------------------------------------------------------------------- -Metrostroi.DefineSystem("81_722_sarmat") +Metrostroi.DefineSystem("81_722_BMCIK") TRAIN_SYSTEM.DontAccelerateSimulation = true +TRAIN_SYSTEM.TriggerNames = { + "SarmatUp", + "SarmatDown", + "SarmatEnter", + "SarmatEsc", + "SarmatF1", + "SarmatF2", + "SarmatF3", + "SarmatF4", + "SarmatPath", + "SarmatLine", + "SarmatZero", + "SarmatStart", +} function TRAIN_SYSTEM:Initialize() - self.Train:LoadSystem("SarmatUp","Relay","Switch") - self.Train:LoadSystem("SarmatDown","Relay","Switch") - self.Train:LoadSystem("SarmatEnter","Relay","Switch") - self.Train:LoadSystem("SarmatEsc","Relay","Switch") - self.Train:LoadSystem("SarmatF1","Relay","Switch") - self.Train:LoadSystem("SarmatF2","Relay","Switch") - self.Train:LoadSystem("SarmatF3","Relay","Switch") - self.Train:LoadSystem("SarmatF4","Relay","Switch") - self.Train:LoadSystem("SarmatPath","Relay","Switch") - self.Train:LoadSystem("SarmatLine","Relay","Switch") - self.Train:LoadSystem("SarmatZero","Relay","Switch") - self.Train:LoadSystem("SarmatStart","Relay","Switch") - self.TriggerNames = { - "SarmatUp", - "SarmatDown", - "SarmatEnter", - "SarmatEsc", - "SarmatF1", - "SarmatF2", - "SarmatF3", - "SarmatF4", - "SarmatPath", - "SarmatLine", - "SarmatZero", - "SarmatStart", - } self.Triggers = {} for k,v in pairs(self.TriggerNames) do - if self.Train[v] then self.Triggers[v] = self.Train[v].Value > 0.5 end + self.Train:LoadSystem(v,"Relay","Switch") + self.Triggers[v] = false end - self.SarmatState = 0 - self.SarmatAnnState = 1 - self.SarmatCamState = 1 - - self.Line = 1 - self.Path = false - self.Station = 1 - self.Arrived = true - - self.Selected = 0 - - self.LineEnabled = false - - self.UPOActive = 0 self.LineOut = 0 + self.UPOActive = 0 + if TURBOSTROI then return end + + self.State = 0 + self.Brightness = 1 + + self.NIIP = { + DOORS_closed = 0, + RUCHKA = 0, + SPEED = 0, + UPO_STATE = 0, + Evacuation = 0, + Vzlom_kabiny = 0, + CabActive = 0 + } + + self.BMTS = { + State = 0, + Text = "", + Update = false + } + + self.Announcer = { + State = 0, + CIKState = 0, + Active = false, + Line = 0, + LimitStation = false, + Path = false, + PathSel = false, + Station = 0, + OnStation = false, + Mode = 3, + TrainTrain = false, + BITTime = false, + LineEnabled = false, + Volumes = { + Cabin = 5, + Salon = 5, + UPOCabin = 5, + UPOSalon = 5, + EmerCab = 5, + V5 = 0 + } + } + + self.List = { + Count = 0, + Selected = 1, + Offset = 0, + States = {} + } + + self.Cam = { + {Link = nil,Ent = NULL}, + {Link = nil,Ent = NULL}, + {Link = nil,Ent = NULL}, + {Link = nil,Ent = NULL}, + Page = 0, + Wagon = 0, + Fullscreen = 0 + } end function TRAIN_SYSTEM:Outputs() @@ -60,1033 +97,2439 @@ function TRAIN_SYSTEM:Outputs() end function TRAIN_SYSTEM:Inputs() - return {"CheckUPO"} + return {} end if TURBOSTROI then return end -function TRAIN_SYSTEM:TriggerInput(name,value) - if name == "CheckUPO" then - local UPOActive = (math.random()>0.05 and not self.Arrived or self.Arrived and not self.Depeating) and self.LineOut==0 - if UPOActive then - if self.Arrived and not self.Depeating then - --self.Train.BUKP.CloseRing = self.Train.BUKP.CloseRing or CurTime()+3 - self.Depeating = true - elseif not self.Arrived then - self.Arrived = true - local stbl = Metrostroi.SarmatUPOSetup[self.Train:GetNW2Int("Announcer",1)] - local stbll = stbl[self.Line] - local last = (self.Path and not stbll.Loop) and self.StartStation or self.EndStation - self.Last = self.Station == last +-- CAN messages +TRAIN_SYSTEM.CAN_ACTIVATE = 0x01 +TRAIN_SYSTEM.CAN_CIKSTATE = 0x02 + +TRAIN_SYSTEM.CAN_BMTS_TEXT = 0x10 + +TRAIN_SYSTEM.CAN_CURR = 0x21 +TRAIN_SYSTEM.CAN_NEXT = 0x22 +TRAIN_SYSTEM.CAN_PATH = 0x23 +TRAIN_SYSTEM.CAN_CLOSERING = 0x24 +TRAIN_SYSTEM.CAN_VOLUMES = 0x25 +TRAIN_SYSTEM.CAN_SPEED = 0x26 + +TRAIN_SYSTEM.CAN_BITTEXT = 0x30 +TRAIN_SYSTEM.CAN_BITDOPMSG = 0x31 +TRAIN_SYSTEM.CAN_BITTIME = 0x32 + +-- Buttons +TRAIN_SYSTEM.Buttons = { + { + name = "Esc", + id = 41, + x = 10,y = 742, + w = 218,h = 48, + touch = function(self) + if self.Cam.Page == 0 then return end + if self.Cam.Fullscreen > 0 then + self.Cam.Fullscreen = 0 + else + self.Cam.Page = 0 + for i=1,4 do + self.Cam[i].Link = nil + self.Cam[i].Ent = NULL + end end - self:UpdateSarmat() + end, + show = function(page) + return true + end + }, + { + name = "<-", + id = 42, + x = 234,y = 742, + w = 217,h = 48, + touch = function(self) + if self.Cam.Page == 0 then return end + if self.Cam.Fullscreen > 0 then return end + self.Cam.Page = self.Cam.Page - 1 + if self.Cam.Page == 0 then + self.Cam.Wagon = self.Cam.Wagon - 1 + if self.Cam.Wagon == 0 then + self.Cam.Wagon = self.Cam.WagNum + end + self.Cam.Page = self.Cam.Cameras[self.Cam.Wagon].Count + end + return true + end, + show = function(page) + return true + end + }, + { + name = "->", + id = 43, + x = 457,y = 742, + w = 218,h = 48, + touch = function(self) + if self.Cam.Page == 0 then return end + if self.Cam.Fullscreen > 0 then return end + self.Cam.Page = self.Cam.Page + 1 + if self.Cam.Page > self.Cam.Cameras[self.Cam.Wagon].Count then + self.Cam.Wagon = self.Cam.Wagon + 1 + if self.Cam.Wagon > self.Cam.WagNum then + self.Cam.Wagon = 1 + end + self.Cam.Page = 1 + end + return true + end, + show = function(page) + return true + end + }, + { + name = "☼", + id = 44, + x = 911,y = 9, + w = 119,h = 32, + touch = function(self) + self.Brightness = self.Brightness + 0.25 + if self.Brightness > 1 then self.Brightness = 0.25 end + self.Train:SetNW2Float("BMCIK:Brightness",self.Brightness) + end, + show = function(page) + return true + end + }, + + -- Наружные камеры + { + name = "Левые", + id = 1, + x = 95,y = 183, + w = 140,h = 60, + touch = function(self) + if self.Cam.Page > 0 then return end + self.Cam.Wagon = 1 + self.Cam.Page = 2 + return true + end, + show = function(page) + return page == 0 + end + }, + { + name = "Передние", + id = 2, + x = 241,y = 183, + w = 140,h = 60, + touch = function(self) + if self.Cam.Page > 0 then return end + self.Cam.Wagon = 1 + self.Cam.Page = 1 + return true + end, + show = function(page) + return page == 0 + end + }, + { + name = "Вокруг", + id = 3, + x = 387,y = 183, + w = 140,h = 60, + touch = function(self) + if self.Cam.Page > 0 then return end + self.Cam.Wagon = 1 + self.Cam.Page = 4 + return true + end, + show = function(page) + return page == 0 + end + }, + { + name = "Задние", + id = 4, + x = 533,y = 183, + w = 140,h = 60, + touch = function(self) + if self.Cam.Page > 0 then return end + self.Cam.Wagon = self.Cam.WagNum + self.Cam.Page = 1 + return true + end, + show = function(page) + return page == 0 + end + }, + { + name = "Правые", + id = 5, + x = 679,y = 183, + w = 140,h = 60, + touch = function(self) + if self.Cam.Page > 0 then return end + self.Cam.Wagon = 1 + self.Cam.Page = 3 + return true + end, + show = function(page) + return page == 0 + end + }, + + -- Камеры на постах машиниста + { + name = "Вагон 1", + id = 21, + x = 215,y = 463, + w = 140,h = 60, + touch = function(self) + if self.Cam.Page > 0 then return end + self.Cam.Wagon = 1 + self.Cam.Page = 6 + return true + end, + show = function(page) + return page == 0 + end + }, + { + name = "Вагон %d", + id = 22, + x = 559,y = 463, + w = 140,h = 60, + touch = function(self) + if self.Cam.Page > 0 then return end + self.Cam.Wagon = self.Cam.WagNum + self.Cam.Page = 3 + return true + end, + show = function(page) + return page == 0 + end + }, + + -- Путевые камеры + { + name = "Вагон 1", + id = 31, + x = 215,y = 603, + w = 140,h = 60, + touch = function(self) + if self.Cam.Page > 0 then return end + self.Cam.Wagon = 1 + self.Cam.Page = 5 + return true + end, + show = function(page) + return page == 0 + end + }, + { + name = "Вагон %d", + id = 32, + x = 559,y = 603, + w = 140,h = 60, + touch = function(self) + if self.Cam.Page > 0 then return end + self.Cam.Wagon = self.Cam.WagNum + self.Cam.Page = 2 + return true + end, + show = function(page) + return page == 0 + end + }, +} +TRAIN_SYSTEM.Buttons.Count = #TRAIN_SYSTEM.Buttons +TRAIN_SYSTEM.CamConfig = { + -- Dummy + [0] = { + Count = 0, + { + PageName = "", + Count = 4, + {"",Vector(0,0,0),Angle(0,0,0)}, + {"",Vector(0,0,0),Angle(0,0,0)}, + {"",Vector(0,0,0),Angle(0,0,0)}, + {"",Vector(0,0,0),Angle(0,0,0)} + }, + }, + -- 722 Head + { + Count = 8, + { + PageName = "Передние зеркала", + Count = 2, + { + "[1] Левый борт, переднее зеркало", + Vector(425, 65,40),Angle(10, 170,0) + }, + { + "[2] Правый борт, переднее зеркало", + Vector(425,-65,40),Angle(10,-170,0) + } + }, + { + Count = 2, + PageName = "Левые зеркала", + + { + "[1] Левый борт, переднее зеркало", + Vector(425, 65,40),Angle(10, 170,0) + }, + { + "[2] Левый борт, заднее зеркало", + Vector(425,-65,40),Angle(10,-170,0), + lastWag = true + } + }, + { + PageName = "Правые зеркала", + Count = 2, + { + "[1] Правый борт, переднее зеркало", + Vector(425,-65,40), + Angle(10,-170,0) + }, + { + "[2] Правый борт, заднее зеркало", + Vector(425,65,40),Angle(10,170,0), + lastWag = true + } + }, + { + PageName = "Бортовые зеркала", + Count = 4, + { + "[1] Левый борт, переднее зеркало", + Vector(425,65,40),Angle(10,170,0) + }, + { + "[2] Правый борт, переднее зеркало", + Vector(425,-65,40),Angle(10,-170,0) + }, + { + "[3] Левый борт, заднее зеркало", + Vector(425,-65,40),Angle(10,-170,0), + lastWag = true + }, + { + "[4] Правый борт, заднее зеркало", + Vector(425,65,40),Angle(10,170,0), + lastWag = true + } + }, + { + PageName = "Путевые камеры", + Count = 1, + { + "[1] Передняя путевая камера", + Vector(490,10,-8),Angle(5,0,0) + } + }, + { + PageName = "Кабина машиниста", + Count = 1, + { + "[1] Передняя кабина", + Vector(410,35,36.5),Angle(33,-15,0) + } + }, + { + PageName = "Салонные камеры", + Count = 4, + { + "[1] Камера в БИТ", + Vector(375,-14,45), + Angle(20,180,0) + }, + { + "[2] Камера в БИТ", + Vector(5,-14,49), + Angle(24,0,0) + }, + { + "[3] Камера в БИТ", + Vector(-450,14,49), + Angle(20,0,0) + }, + { + "[4] Камера в БИТ", + Vector(-8,14,49), + Angle(24,180,0) + } + }, + { + PageName = "Салонные камеры", + Count = 2, + { + "[1] Камера в БЭС", + Vector(150,-50,20), + Angle(5,95,0), + wide = true + }, + { + "[2] Камера в БЭС", + Vector(-156, 50,20), + Angle(5,-85,0), + wide = true + } + } + }, + -- 722 Back + { + Count = 6, + + { + PageName = "Задние зеркала", + Count = 2, + { + "[1] Левый борт, заднее зеркало", + Vector(425,-65,40), + Angle(10,-170,0) + }, + { + "[2] Правый борт, заднее зеркало", + Vector(425,65,40), + Angle(10,170,0) + } + }, + { + PageName = "Путевые камеры", + Count = 1, + { + "[1] Задняя путевая камера", + Vector(490,10,-8), + Angle(5,0,0) + } + }, + { + PageName = "Кабина машиниста", + Count = 1, + { + "[1] Задняя кабина", + Vector(410,35,36.5), + Angle(33,-15,0) + } + }, + { + PageName = "Салонные камеры", + Count = 4, + { + "[1] Левое зеркало", + Vector(425,-65,40), + Angle(10,-170,0) + }, + { + "[2] Правое зеркало", + Vector(425, 65,40), + Angle(10, 170,0) + }, + { + "[3] Путевая камера", + Vector(490,10,-8), + Angle(5,0,0) + }, + { + "[4] Камера в кабине машиниста", + Vector(410,35,36.5), + Angle(33,-15,0) + } + }, + { + PageName = "Салонные камеры", + Count = 4, + { + "[1] Камера в БИТ", + Vector(-450,14,49), + Angle(20,0,0) + }, + { + "[2] Камера в БИТ", + Vector(-8,14,49), + Angle(24,180,0) + }, + { + "[3] Камера в БИТ", + Vector(375,-14,45), + Angle(20,180,0) + }, + { + "[4] Камера в БИТ", + Vector(5,-14,49), + Angle(24,0,0) + } + }, + { + PageName = "Салонные камеры", + Count = 2, + { + "[1] Камера в БЭС", + Vector(150,-50,20), + Angle(5,95,0), + wide = true + }, + { + "[2] Камера в БЭС", + Vector(-156, 50,20), + Angle(5,-85,0), + wide = true + } + } + }, + -- 723/724 Intermediate + { + Count = 2, + { + PageName = "Салонные камеры", + Count = 4, + { + "[1] Камера в БИТ", + Vector(450,-14,49), + Angle(20,180,0) + }, + { + "[2] Камера в БИТ", + Vector(5,-14,49), + Angle(24,0,0) + }, + { + "[3] Камера в БИТ", + Vector(-450,14,49), + Angle(20,0,0) + }, + { + "[4] Камера в БИТ", + Vector(-8,14,49), + Angle(24,180,0) + } + }, + { + PageName = "Салонные камеры", + Count = 2, + { + "[1] Камера в БЭС", + Vector(150,-50,20), + Angle(5,95,0), + wide = true + }, + { + "[2] Камера в БЭС", + Vector(-156, 50,20), + Angle(5,-85,0), + wide = true + } + } + } +} +TRAIN_SYSTEM.SettingsList = { + {"Ввод номера маршрута",nil}, + {"Режимы работы информатора","AnnModeList"}, + {"Режимы работы СОСТАВ-СОСТАВ",nil}, + {"Настройка громкости","AnnVolumeList"}, + {"Информация","InfoList"}, + {"Диагностика","DiagList"}, + {"Язык","LangList"}, + {"Время на БИТ","BITClockList"} +} +TRAIN_SYSTEM.AnnModeList = { + "Режим 'Информатор'", + "Режим 'УПО+Информатор'", + "Режим 'УПО+Информатор+Пуск'", + "Режим 'УПО'" +} +TRAIN_SYSTEM.AnnVolumeList = { + {"Громкость инф. в кабине","Cabin",0,10}, + {"Громкость инф. в салоне","Salon",1,10}, + {"Громкость УПО в кабине","UPOCabin",0,10}, + {"Громкость УПО в салоне","UPOSalon",1,10}, + {"Громкость ЭКСТР./МЕЖКАБ.","EmerCab",0,10}, + {"Увеличение при V>5 на","V5",0,10} +} +TRAIN_SYSTEM.InfoList = { + {"MIES firmware version 20181203",nil}, + {"NIIP DOORS_closed= ","BMCIK:AddInfoNIIPDoors"}, + {"NIIP RUCHKA= ",nil}, + {"NIIP SPEED= ","BMCIK:AddInfoNIIPSpeed"}, + {"NIIP UPO_STATE= ","BMCIK:AddInfoUPO"}, + {"NIIP Evacuation= ",nil}, + {"NIIP Vzlom_kabiny= ",nil}, + {"Video sended= ","BMCIK:AddInfoVideo"}, + {"AVT.State.State_byte= ",nil}, + {"AVT.Now_S.code= ",nil}, + {"AVT.Next_S.code= ",nil}, + {"AVT.Final_S.code= ",nil}, + {"AVT.Met= ",nil} +} +TRAIN_SYSTEM.DiagList = { + "Advanced LAN diagnostics", + "Advanced CAN diagnostics", + "BMCIK 0/0", + "MIES 0/0", + "MDU 0/0", + "MAR 0/0", + "BES LAN 0/0", + "BES CAN 0/0", + "BNT(BUM) 0/0", + "BIT 0/0", + "BVK 0/0", + "BMTS 0/0" +} +TRAIN_SYSTEM.LangList = { + "Russian", + -- "English", + -- "Hungarian" +} +TRAIN_SYSTEM.BITClockList = { + "Время выключено", + "Время включено" +} + +TRAIN_SYSTEM.CIKStatesNames = { + [0] = "Готов", + [1] = "Воспроизведение...", + [2] = "Межкабинная связь активна", + [3] = "Громкая связь", + -- [4] = "Нет связи", + -- [5] = "Связь восстановлена", + -- [6] = "Линия свободна" +} + +TRAIN_SYSTEM.HeaderNames = { + [0] = "---", + [1] = "---", + [11] = "Предупредительные\nсообщения", + [12] = "Ограничение маршрута", + [13] = "Дополнительные сообщения", + [14] = "Экстренные сообщения", + [15] = "Выбор линии", + [2] = "Меню настройки блока\nСБУЦИК", + [21] = "Меню настройки блока\nСБУЦИК", + [22] = "Режимы работы\nинформатора", + [23] = "Режимы работы блока\nСБУЦИК", + [24] = "Настройка громкости", + [25] = "Additional information", + [26] = "Диагностика (0%)", + [27] = "Язык", + [28] = "Отображение времени на\nБИТ" +} + +local function setBitValue(targetVar, value, offset, bitCount) + value = bit.band(value,bit.lshift(1,bitCount)-1) + return bit.bor(targetVar,bit.lshift(value,offset)) +end + +local function getBitValue(value, offset, bitCount) + local mask = bit.lshift(bit.lshift(1,bitCount)-1,offset) + return bit.rshift(bit.band(value,mask),offset) +end + +-- Announcer functions +function TRAIN_SYSTEM:Announcer_Reset(resetAnn) + local Announcer = self.Announcer + self:Announcer_Stop() + self:Announcer_CabStop() + Announcer.State = 0 + Announcer.CIKState = 0 + Announcer.Active = false + if resetAnn then + Announcer.Line = 0 + Announcer.Volumes.Cabin = 5 + Announcer.Volumes.Salon = 5 + Announcer.Volumes.UPOCabin = 5 + Announcer.Volumes.UPOSalon = 5 + Announcer.Volumes.EmerCab = 5 + Announcer.Volumes.V5 = 0 + + Announcer.BITTime = false + end + + Announcer.LimitStation = false + Announcer.Path = false + Announcer.PathSel = false + Announcer.Station = 0 + Announcer.OnStation = false + Announcer.Mode = 3 + Announcer.TrainTrain = false + Announcer.LineEnabled = false + + self.Train:SetNW2Int("BMCIK:Announcer",0) + self.Train:SetNW2Bool("BMCIK:LineEnabled",false) +end + +function TRAIN_SYSTEM:Announcer_Activate(forceActive) + local Announcer = self.Announcer + if (not forceActive and Announcer.Active) or Announcer.Line == 0 then return end + + -- TODO: Try to implement better logic of UPO noise sync + local Train = self.Train + local noiseVolume = Train.UPONoiseVolume + local upoVolume = Train.UPOVolume + local wagList = Train.WagonList + for i=1,#wagList do + wagList[i]:SetNW2Float("UPONoiseVolume",noiseVolume) + wagList[i]:SetNW2Float("UPOVolume",upoVolume) + end + + self:Announcer_FindLimitStations() + Announcer.LimitStation = false + self:Announcer_Zero() + self:Announcer_SetState(1,#Metrostroi.SarmatUPOSetup[Train:GetNW2Int("Announcer")][Announcer.Line]*2) +end + +function TRAIN_SYSTEM:Announcer_SetState(state,count) + local Announcer = self.Announcer + self:List_Save(Announcer.State) + Announcer.PrevState = Announcer.State + Announcer.State = state + self:List_Reset(count) +end + +function TRAIN_SYSTEM:Announcer_FindLimitStations() + local Announcer = self.Announcer + local lTbl = Metrostroi.SarmatUPOSetup[self.Train:GetNW2Int("Announcer")][Announcer.Line] + Announcer.LastStations = {} + if lTbl.Loop then + for i=1,#lTbl do + if lTbl[i].arrlast then table.insert(Announcer.LastStations,i) end + end + else + for i=2,#lTbl-1 do + if lTbl[i].arrlast then table.insert(Announcer.LastStations,i) end end - self.UPOActive = UPOActive and 1 or 0 - self.UPOLock = UPOActive and CurTime() - return UPOActive end end -TRAIN_SYSTEM.Specials = {[-4]="Еду на море",[-3]="На порезку",[-2]="Обкатка",[-1]="Перегонка",[0]="В депо"} -if SERVER then - local function InRange(x,y,px,py,pw,ph) - local hpw,hph = pw/2,ph/2 - return (px-hpw < x and x < px+hpw) and (py-hph < y and y < py+hph) - end - function TRAIN_SYSTEM:Touch(value,x,y) - local Train = self.Train - if self.SarmatCamState == 1 and value then - local WagNum = #Train.WagonList - if InRange(x,y,124,140,113,40,"Левые") then - self.Cam1,self.Cam1E = CurTime()+math.Rand(0.4,4),Train - self.Cam2,self.Cam2E = CurTime()+math.Rand(0.4,4),Train.WagonList[WagNum] - self.Cam3,self.Cam4 = false,false - self.SarmatCamState,self.SarmatCamCount,self.SarmatCamType = 2,2,1 - end - if InRange(x,y,242,140,113,40,"Передние") then - self.Cam1,self.Cam1E = CurTime()+math.Rand(0.4,4),Train - self.Cam2,self.Cam2E = CurTime()+math.Rand(0.4,4),Train - self.Cam3,self.Cam4 = false,false - self.SarmatCamState,self.SarmatCamCount,self.SarmatCamType = 2,2,2 - end - if InRange(x,y,360,140,113,40,"Вокруг") then - self.Cam1,self.Cam1E = CurTime()+math.Rand(0.4,4),Train - self.Cam2,self.Cam2E = CurTime()+math.Rand(0.4,4),Train - self.Cam3,self.Cam3E = CurTime()+math.Rand(0.4,4),Train.WagonList[WagNum] - self.Cam4,self.Cam4E = CurTime()+math.Rand(0.4,4),Train.WagonList[WagNum] - self.SarmatCamState,self.SarmatCamCount,self.SarmatCamType = 4,4,3 - end - if InRange(x,y,478,140,113,40,"Задние") then - self.Cam1,self.Cam1E = CurTime()+math.Rand(0.4,4),Train.WagonList[WagNum] - self.Cam2,self.Cam2E = CurTime()+math.Rand(0.4,4),Train.WagonList[WagNum] - self.Cam3,self.Cam4 = false,false - self.SarmatCamState,self.SarmatCamCount,self.SarmatCamType = 3,2,4 - end - if InRange(x,y,596,140,113,40,"Правые") then - self.Cam1,self.Cam1E = CurTime()+math.Rand(0.4,4),Train - self.Cam2,self.Cam2E = CurTime()+math.Rand(0.4,4),Train.WagonList[WagNum] - self.Cam3,self.Cam4 = false,false - self.SarmatCamState,self.SarmatCamCount,self.SarmatCamType = 3,2,5 - end - for i=1+self.Selected,math.min(WagNum,6+self.Selected) do - if InRange(x,y,65+(i-1-self.Selected)*118+118*math.max(0,6-WagNum)/2 ,235,113,40,"Вагон "..i) then - self.Cam1,self.Cam1E = CurTime()+math.Rand(0.4,4),Train.WagonList[i] - self.Cam2,self.Cam2E = CurTime()+math.Rand(0.4,4),Train.WagonList[i] - self.Cam3,self.Cam3E = CurTime()+math.Rand(0.4,4),Train.WagonList[i] - self.Cam4,self.Cam4E = CurTime()+math.Rand(0.4,4),Train.WagonList[i] - self.SarmatCamState,self.SarmatCamCount,self.SarmatCamType = 5,4,6 - end - end +function TRAIN_SYSTEM:Announcer_Zero() + local Announcer = self.Announcer + local Train = self.Train + local lTbl = Metrostroi.SarmatUPOSetup[Train:GetNW2Int("Announcer")][Announcer.Line] + if Announcer.Line < 1 then return end - if InRange(x,y,220,350,113,40,"Вагон 1") then - self.Cam1,self.Cam1E = CurTime()+math.Rand(0.4,4),Train - self.Cam2,self.Cam3,self.Cam4 = false,false - self.SarmatCamState,self.SarmatCamCount,self.SarmatCamType = 6,1,7 - end - if InRange(x,y,500,350,113,40,"Вагон "..WagNum) then - self.Cam1,self.Cam1E = CurTime()+math.Rand(0.4,4),Train.WagonList[WagNum] - self.Cam2,self.Cam3,self.Cam4 = false,false - self.SarmatCamState,self.SarmatCamCount,self.SarmatCamType = 6,1,8 - end + self:Announcer_Stop() + Announcer.Active = true + Announcer.Path = Announcer.PathSel + Announcer.Station = Announcer.Path and #lTbl or 1 + Announcer.OnStation = false + Announcer.AVTDepart = false - if InRange(x,y,220,465,113,40,"Вагон 1") then - self.Cam1,self.Cam1E = CurTime()+math.Rand(0.4,4),Train - self.Cam2,self.Cam3,self.Cam4 = false,false - self.SarmatCamState,self.SarmatCamCount,self.SarmatCamType = 7,1,9 - end - if InRange(x,y,500,465,113,40,"Вагон "..WagNum) then - self.Cam1,self.Cam1E = CurTime()+math.Rand(0.4,4),Train.WagonList[WagNum] - self.Cam2,self.Cam3,self.Cam4 = false,false - self.SarmatCamState,self.SarmatCamCount,self.SarmatCamType = 7,1,10 - end - --surface.DrawTexturedRectRotated(110,590,200,40,0) - --draw.SimpleText("Esc","Metrostroi_Arial20",110,590, Color(200,200,200),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) + Train:CANWrite("BMCIK",nil,"BNT",nil,self.CAN_CLOSERING,false) + Train:CANWrite("BMCIK",Train:GetWagonNumber(),"BMCIK",nil,self.CAN_ACTIVATE) + Train:CANWrite("BMCIK",nil,"BNT",nil,self.CAN_ACTIVATE) + Train:CANWrite("BMCIK",nil,"BIT",nil,self.CAN_ACTIVATE) + Train:CANWrite("BMCIK",nil,"BNT",nil,self.CAN_VOLUMES,{Announcer.Volumes.Salon,Announcer.Volumes.UPOSalon,Announcer.Volumes.V5}) + self:BMTS_Update() + self:CANUpdate() +end - if InRange(x,y,320,590,200,40,"<-") then - self.Selected = math.max(self.Selected - 1,0) +function TRAIN_SYSTEM:Announcer_Prev() + local Announcer = self.Announcer + local lTbl = Metrostroi.SarmatUPOSetup[self.Train:GetNW2Int("Announcer")][Announcer.Line] + if Announcer.OnStation then + Announcer.OnStation = false + else + if Announcer.Path then + if #lTbl > Announcer.Station then + Announcer.Station = Announcer.Station+1 + Announcer.OnStation = true end - if InRange(x,y,530,590,200,40,"->") then - self.Selected = math.Clamp(self.Selected + 1,0,#Train.WagonList-6) + else + if Announcer.Station > 1 then + Announcer.Station = Announcer.Station-1 + Announcer.OnStation = true end end - if self.SarmatCamState > 1 and value then - if InRange(x,y,110,590,200,40,"Esc") then - self.SarmatCamState = 1 - self.Cam1 = false - self.Cam2 = false - self.Cam3 = false - self.Cam4 = false - self.Selected = 0 + end +end + +function TRAIN_SYSTEM:Announcer_Next(returnToStart) + local Announcer = self.Announcer + local lTbl = Metrostroi.SarmatUPOSetup[self.Train:GetNW2Int("Announcer")][Announcer.Line] + local maxStation = Announcer.LimitStation or (Announcer.Path and 1 or #lTbl) + if Announcer.OnStation then + if Announcer.Path then + if Announcer.Station > maxStation then + Announcer.Station = Announcer.Station-1 + Announcer.OnStation = false + elseif returnToStart and maxStation == Announcer.Station then + Announcer.Station = #lTbl + Announcer.OnStation = false + return true + end + else + if maxStation > Announcer.Station then + Announcer.Station = Announcer.Station+1 + Announcer.OnStation = false + elseif returnToStart and maxStation == Announcer.Station then + Announcer.Station = 1 + Announcer.OnStation = false + return true end end - Train:SetNW2Int("SarmatCamSelected",self.Selected) + else + Announcer.OnStation = true + local last = not lTbl.Loop and Announcer.Station == (Announcer.Path and 1 or #lTbl) + if Announcer.LimitStation then + last = Announcer.LimitStation == Announcer.Station + end + Announcer.CurrentLast = last + end +end + +function TRAIN_SYSTEM:Announcer_Queue(msg) + local AnnouncerSys = self.Train.Announcer + if msg and type(msg) ~= "table" then + AnnouncerSys:Queue{msg} + else + AnnouncerSys:Queue(msg) + end +end + +function TRAIN_SYSTEM:Announcer_CabPlay() + if self.LineOut > 0 then return end + local Announcer = self.Announcer + local lTbl = Metrostroi.SarmatUPOSetup[self.Train:GetNW2Int("Announcer")][Announcer.Line] + if not lTbl then return end + local sTbl = lTbl[Announcer.Station] + + Announcer.CabPlay = true + self.Train:CANWrite("BMCIK",nil,"BNT",nil,self.CAN_VOLUMES,{0,0,0}) + + self.Train.Announcer.AnnounceTimer = CurTime()+0.2 -- Silent sound fix at begin playing + self:Announcer_Queue("tone") + local message + local last = not lTbl.Loop and Announcer.Station == (Announcer.Path and 1 or #lTbl) + if Announcer.LimitStation then + last = Announcer.LimitStation == Announcer.Station + end + if Announcer.OnStation then + if sTbl.odz then self:Announcer_Queue(sTbl.odz) end + message = sTbl.dep and sTbl.dep[Announcer.Path and 2 or 1] + else + if last then + message = sTbl.arrlast and sTbl.arrlast[Announcer.Path and 2 or 1] + else + message = sTbl.arr and sTbl.arr[Announcer.Path and 2 or 1] + end end - function TRAIN_SYSTEM:Zero() - local stbl = Metrostroi.SarmatUPOSetup[self.Train:GetNW2Int("Announcer",1)] - local stbll = stbl[self.Line] - if not stbll then - self:UpdateSarmat() + if not message then return end + self:Announcer_Queue(message) +end + +function TRAIN_SYSTEM:Announcer_CabStop() + local Announcer = self.Announcer + if not Announcer.CabPlay then return end + Announcer.CabPlay = false + self.Train:CANWrite("BMCIK",nil,"BNT",nil,self.CAN_VOLUMES,{Announcer.Volumes.Salon,Announcer.Volumes.UPOSalon,Announcer.Volumes.V5}) +end + +function TRAIN_SYSTEM:Announcer_Play() + local Announcer = self.Announcer + if Announcer.UPOLock then return end + if Announcer.Mode > 3 then return end + local lTbl = Metrostroi.SarmatUPOSetup[self.Train:GetNW2Int("Announcer")][Announcer.Line] + if not lTbl then return end + local sTbl = lTbl[Announcer.Station] + self:Announcer_Stop() + self:Announcer_Queue("tone") + local message + local last = not lTbl.Loop and Announcer.Station == (Announcer.Path and 1 or #lTbl) + if Announcer.LimitStation then + last = Announcer.LimitStation == Announcer.Station + end + if Announcer.OnStation then + if sTbl.odz then self:Announcer_Queue(sTbl.odz) end + message = sTbl.dep and sTbl.dep[Announcer.Path and 2 or 1] + else + if last then + message = sTbl.arrlast and sTbl.arrlast[Announcer.Path and 2 or 1] + self:Announcer_Queue(-1) + else + message = sTbl.arr and sTbl.arr[Announcer.Path and 2 or 1] + end + end + Announcer.CurrentLast = last + if not message then return end + self:Announcer_Queue(message) +end + +function TRAIN_SYSTEM:Announcer_Stop() + self:Announcer_CabStop() + self.LineOut = 0 + self.UPOActive = 0 + self.Announcer.UPOLock = false + self.Train.Announcer.AnnounceTimer = CurTime()+0.2 -- Silent sound fix at begin playing + self.Train.Announcer:TriggerInput("Reset","AnnouncementsSarmatUPO") +end + +-- Cameras control functions +function TRAIN_SYSTEM:Cam_Scan() + local Cam = self.Cam + local Train = self.Train + local wagList = Train.WagonList + Cam.WagNum = #wagList + Cam.Cameras = {} + + local lastWag = wagList[Cam.WagNum] + for w=1,Cam.WagNum do + local iWag = wagList[w] + local iWagType = w==1 and 1 or (iWag.SubwayTrain.WagType==1 and w==Cam.WagNum) and 2 or 3 + local wagCamTbl = self.CamConfig[iWagType] + Cam.Cameras[w] = { + wagEnt = iWag, + wagNum = iWag:GetWagonNumber(), + wagType = iWagType, + Count = wagCamTbl.Count + } + for page=1,wagCamTbl.Count do + Cam.Cameras[w][page] = {} + for iCam=1,wagCamTbl[page].Count do + Cam.Cameras[w][page][iCam] = wagCamTbl[page][iCam].lastWag and lastWag or iWag + end + end + end + Cam.TrainLen = Cam.WagNum*20 + Cam.LoadingTimer = nil + Train:SetNW2Int("BMCIK:WagNum",Cam.WagNum) +end + +function TRAIN_SYSTEM:Cam_Open(wagon,page) + local Cam = self.Cam + if Cam.Page > 0 then return end + + Cam.AutoOpen = true + Cam.Distance = 0 + Cam.Wagon = wagon + Cam.Page = page + + for i=1,4 do + Cam[i].Link = CurTime()+math.Rand(0.2,1) + Cam[i].Ent = Cam.Cameras[Cam.Wagon][Cam.Page][i] + if i > #Cam.Cameras[Cam.Wagon][Cam.Page] then + Cam[i].Link = nil + Cam[i].Ent = NULL + end + end + + local Train = self.Train + Train:SetNW2Int("BMCIK:CamWagIndex",Cam.Wagon) + Train:SetNW2Int("BMCIK:CamType",Cam.Cameras[Cam.Wagon].wagType) + Train:SetNW2Int("BMCIK:CamWagNumber",Cam.Cameras[Cam.Wagon].wagNum) +end + +function TRAIN_SYSTEM:Cam_Close() + local Cam = self.Cam + Cam.Page = 0 + for i=1,4 do + Cam[i].Link = nil + Cam[i].Ent = NULL + end + + local Train = self.Train + Train:SetNW2Int("BMCIK:CamWagIndex",0) + Train:SetNW2Int("BMCIK:CamType",0) + Train:SetNW2Int("BMCIK:CamWagNumber",0) +end + +function TRAIN_SYSTEM:Cam_Reset() + local Cam = self.Cam + Cam.Page = 0 + Cam.Wagon = 0 + Cam.Fullscreen = 0 + Cam.AutoOpen = false + Cam[1] = {Link = nil,Ent = NULL} + Cam[2] = {Link = nil,Ent = NULL} + Cam[3] = {Link = nil,Ent = NULL} + Cam[4] = {Link = nil,Ent = NULL} +end + +-- List functions +function TRAIN_SYSTEM:List_Save(state) + local List = self.List + List.States[state] = {Count = List.Count,Selected = List.Selected,Offset = List.Offset} +end + +function TRAIN_SYSTEM:List_Load(state) + local List = self.List + if not List.States[state] then return end + local saveState = List.States[state] + saveState.Selected = math.min(saveState.Selected,saveState.Count) + local dOffset = saveState.Count - saveState.Offset - 21 + if dOffset < 0 then + saveState.Offset = math.max(0,saveState.Offset + dOffset) + end + List.Count = saveState.Count + List.Selected = saveState.Selected + List.Offset = saveState.Offset + List.States[state] = nil +end + +function TRAIN_SYSTEM:List_Set(state, sel) + local List = self.List + if state and self.Announcer.State ~= state and List.States[state] then List = List.States[state] end + if sel == List.Selected or sel > List.Count then return end + List.Selected = sel + + local cursorPos = List.Selected - List.Offset + local dOffset + if cursorPos < 1 then + dOffset = cursorPos - 1 + elseif cursorPos > 21 then + dOffset = cursorPos - 21 + end + if dOffset then + List.Offset = math.Clamp(List.Offset + dOffset,0,List.Count-21) + end +end + +function TRAIN_SYSTEM:List_GetSelectedItem() + return self.List.Selected +end + +function TRAIN_SYSTEM:List_Prev(state) + local List = self.List + if state and self.Announcer.State ~= state and List.States[state] then List = List.States[state] end + if List.Count < 2 then return end + local lastSel = List.Selected + List.Selected = math.max(1,List.Selected - 1) + if List.Selected-List.Offset == 0 and List.Selected ~= lastSel then + List.Offset = List.Offset-1 + end +end + +function TRAIN_SYSTEM:List_Next(state) + local List = self.List + if state and self.Announcer.State ~= state and List.States[state] then List = List.States[state] end + if List.Count < 2 then return end + local lastSel = List.Selected + List.Selected = math.min(List.Count,List.Selected + 1) + if List.Selected-List.Offset > 21 and List.Selected ~= lastSel then + List.Offset = List.Offset+1 + end +end + +function TRAIN_SYSTEM:List_Reset(count) + local List = self.List + List.Selected = 1 + List.Offset = 0 + List.ListTimer = nil + List.ListTimerDir = nil + List.Count = count or 0 +end + +function TRAIN_SYSTEM:CANReceive(source,sourceid,target,targetid,textdata,numdata) + if textdata == self.CAN_BMTS_TEXT then + self.BMTS.Text = numdata + self.BMTS.Update = true + return + end + if sourceid == self.Train:GetWagonNumber() then return end + if textdata == self.CAN_ACTIVATE then + if self.Announcer.Active then + self.Announcer.Active = false + self.Announcer.AVTDepart = false + self:Cam_Close() + end + end + if textdata == self.CAN_CIKSTATE then + self.Announcer.CIKStateIntercab = numdata + end +end + +function TRAIN_SYSTEM:TriggerInput(name,value) + if not self.Announcer.Active then return end + if name == "OpenDoors" then + if value == 0x4C then + self:Cam_Open(1,2) + elseif value == 0x52 then + self:Cam_Open(1,3) + end + end + local Announcer = self.Announcer + if name == "CheckUPO" then + if self.UPOActive == 0 or self.LineOut>0 or math.random()>0.95 then + return false + end + if not Announcer.OnStation then + self:Announcer_Next() + self:List_Next(1) + self:CANUpdate() + end + return true + end + + if name == "ClosedDoors" then + self.Train:CANWrite("BMCIK",nil,"BNT",nil,self.CAN_CLOSERING,false) + end + if name == "OpenDoors" then + self.Train:CANWrite("BMCIK",nil,"BNT",nil,self.CAN_CLOSERING,false) + if Announcer.AVTDepart then + Announcer.AVTDepart = false + self:CANUpdate() return end - if stbll.Loop then - self.Station = self.Path and #stbll or 1 - else - self.Station = self.Path and self.EndStation or self.StartStation + if not Announcer.OnStation then + self:Announcer_Play() + self:Announcer_Next() + self:List_Next(1) + self:CANUpdate() + end + end + if name == "CloseDoorsAVT" then + Announcer.AVTDepart = Announcer.OnStation + if Announcer.AVTDepart then + self:Announcer_Play() + self:CANUpdate() + end + self.Train:CANWrite("BMCIK",nil,"BNT",nil,self.CAN_CLOSERING,true) + end +end + +function TRAIN_SYSTEM:CANUpdate() + local Announcer = self.Announcer + local lTbl = Metrostroi.SarmatUPOSetup[self.Train:GetNW2Int("Announcer")][Announcer.Line] + local lTblCount = #lTbl + local ledTbl = lTbl.LED or {} + local currLed, nextLed = 0,0 + local station = Announcer.Station + if Announcer.AVTDepart then + if Announcer.Path then + station = station - 1 + if station < 1 then station = #ledTbl end + else + station = station + 1 + if station > #ledTbl then station = 1 end end - self.Arrived = true - self.Depeating = false - self:UpdateSarmat() end - function TRAIN_SYSTEM:Next() - local stbl = Metrostroi.SarmatUPOSetup[self.Train:GetNW2Int("Announcer",1)] - local stbll = stbl[self.Line] - if not stbll then return end - local last = (self.Path and not stbll.Loop) and self.StartStation or self.EndStation - if stbll.Loop then - if self.Arrived then - if self.Path then - self.Station = math.max(0,self.Station - 1) - if self.Station <= 0 then self.Station = #stbll end - else - local max = #stbll - if self.Station >= max then self.Station = 0 end - self.Station = math.min(max,self.Station + 1) - end - self.Arrived = false + for i=(Announcer.Path and #ledTbl or 1),station,(Announcer.Path and -1 or 1) do + currLed = currLed + (ledTbl[i] or 0) + end + if Announcer.AVTDepart or not Announcer.OnStation then + nextLed = ledTbl[station] or 0 + currLed = currLed - nextLed + end + + local sTbl = lTbl[station] + local first,sTblPrev,sTblNext + if lTbl.Loop and not Announcer.Limit then + first = 0 + if Announcer.Path then + sTblNext = ((station-1) < 1) and lTbl[lTblCount] or lTbl[station-1] + sTblPrev = ((station+1) > lTblCount) and lTbl[1] or lTbl[station+1] + else + sTblPrev = ((station-1) < 1) and lTbl[lTblCount] or lTbl[station-1] + sTblNext = ((station+1) > lTblCount) and lTbl[1] or lTbl[station+1] + end + else + if Announcer.Path then + first = lTblCount + sTblPrev = station < lTblCount and lTbl[station+1] + sTblNext = station > 1 and lTbl[station-1] + else + first = 1 + sTblPrev = station > 1 and lTbl[station-1] + sTblNext = station < lTblCount and lTbl[station+1] + end + end + + local bitText = "---" + local bitLeft,bitRight + local bitLoop = 1 + + if not Announcer.AVTDepart and Announcer.OnStation then + if Announcer.CurrentLast then + bitLeft = "" + bitRight = Format("%s >",sTbl[2]) + bitLoop = 4 + + bitText = Format("%%rПоезд прибыл\n%%rна конечную станцию\n%%r%s",sTbl[2]) + if sTbl.right_doors then + bitText = bitText..",\n%%rвыход\n%%rна правую сторону.\n" + bitLoop = bitLoop + 2 else - if self.Station ~= (self.EndStation > 0 and self.EndStation or -1) then - self.Arrived = true - end + bitText = bitText..".\n" end else - if self.Last then - self.Station = self.Path and self.EndStation or self.StartStation - self.Arrived = true - elseif self.Arrived then - if self.Path then - self.Station = math.max(self.StartStation,self.Station - 1) - else - self.Station = math.min(self.EndStation,self.Station + 1) - end - self.Arrived = false + bitLeft = sTblPrev and sTblPrev[2] or "" + bitRight = sTblNext and Format("%s >",sTblNext[2]) + bitLoop = 5 + bitText = Format("%%yСтанция\n%%y%s",sTbl[2]) + if sTbl.right_doors then + bitText = bitText..",\n%%yвыход\n%%yна правую сторону.\n" + bitLoop = bitLoop + 2 else - if self.Station ~= (self.Path and self.StartStation or self.EndStation) then - self.Arrived = true - end + bitText = bitText..".\n" end - end - self.Last = self.Station == last - self.Depeating = false - self:UpdateSarmat() - end - function TRAIN_SYSTEM:Prev() - local stbl = Metrostroi.SarmatUPOSetup[self.Train:GetNW2Int("Announcer",1)] - local stbll = stbl[self.Line] - if not stbll then return end - if stbll.Loop then - if not self.Arrived then - if self.Path then - if self.Station >= #stbll then self.Station = 0 end - self.Station = math.min(#stbll,self.Station + 1) - else - self.Station = math.max(0,self.Station - 1) - if self.Station <= 0 then self.Station = #stbll end - if self.Station == self.EndStation then - self:Prev() - end - end - self.Arrived = true + + bitText = bitText..Format("%%yСледующая станция\n%%y%s",sTblNext[2]) + if sTblNext and sTblNext.right_doors then + bitText = bitText..",\n%%yвыход\n%%yна правую сторону.\n" + bitLoop = bitLoop + 2 else - self.Arrived = false + bitText = bitText..".\n" end + end + + if sTbl.messagearr then + bitLoop = bitLoop + #string.Explode("\n",sTbl.messagearr) + bitText = bitText..(sTbl.messagearr).."\n" + end + bitText = bitText.."\n." + elseif Announcer.AVTDepart or station ~= first then + bitLeft = sTblPrev and sTblPrev[2] + bitRight = Format("%s >",sTbl[2]) + bitLoop = 5 + bitText = Format("%%rОсторожно,\n%%rдвери закрываются!\n%%yСледующая станция\n%%y%s",sTbl[2]) + if sTbl.right_doors then + bitText = bitText..",\n%%yвыход\n%%yна правую сторону.\n" + bitLoop = bitLoop + 2 else - if not self.Arrived then - if self.Path then - self.Station = math.min(self.EndStation,self.Station + 1) + bitText = bitText..".\n" + end + + if sTblPrev and sTblPrev.messagedep then + bitLoop = bitLoop + #string.Explode("\n",sTblPrev.messagedep) + bitText = bitText..(sTblPrev.messagedep).."\n" + end + bitText = bitText.."\n." + end + + self.Train:CANWrite("BMCIK",nil,"BNT",nil,self.CAN_CURR,currLed) + self.Train:CANWrite("BMCIK",nil,"BNT",nil,self.CAN_NEXT,nextLed) + self.Train:CANWrite("BMCIK",nil,"BNT",nil,self.CAN_PATH,Announcer.Path) + self.Train:CANWrite("BMCIK",nil,"BIT",nil,self.CAN_BITTEXT,{Text = string.Explode("\n",bitText), Left = bitLeft, Right = bitRight, Loop = bitLoop}) +end + +function TRAIN_SYSTEM:BMTS_Update() + local lTbl = Metrostroi.SarmatUPOSetup[self.Train:GetNW2Int("Announcer")][self.Announcer.Line] + local bmtsText = lTbl[self.Announcer.LimitStation or (self.Announcer.Path and 1 or #lTbl)][2] + if lTbl.Loop and not self.Announcer.LimitStation then bmtsText = "КОЛЬЦЕВОЙ" end + self.Train:CANWrite("BMCIK",nil,"BMCIK",nil,self.CAN_BMTS_TEXT,bmtsText) +end + +local function InRange(px,py,x,y,w,h) + return (px >= x and px <= (x+w) and py >= y and py <= (y+h)) +end +function TRAIN_SYSTEM:Touch(value,x,y) + if self.State < 1 then return end + local btnID = 0 + local newPage = false + + if self.Cam.Page > 0 then + if not value and self.Cam.Fullscreen == 0 then + local camCountPage = #self.Cam.Cameras[self.Cam.Wagon][self.Cam.Page] + if camCountPage == 4 then + if InRange(x,y,24,58,430,328,"[1]") then + self.Cam.Fullscreen = 1 + elseif InRange(x,y,460,58,430,328,"[2]") then + self.Cam.Fullscreen = 2 + elseif InRange(x,y,24,392,430,328,"[3]") then + self.Cam.Fullscreen = 3 + elseif InRange(x,y,460,392,430,328,"[4]") then + self.Cam.Fullscreen = 4 + end + elseif camCountPage == 2 then + if InRange(x,y,24,58,430,662,"[1]") then + self.Cam.Fullscreen = 1 + elseif InRange(x,y,460,58,430,662,"[2]") then + self.Cam.Fullscreen = 2 + end + end + end + else + local wagNum = self.Cam.WagNum + for i=1,wagNum do + if (wagNum == 8 and InRange(x,y,350+(i-wagNum/2)*110,323,104,60)) + or (wagNum == 7 and InRange(x,y,334+(i-wagNum/2)*126,323,120,60)) + or (wagNum <= 6 and InRange(x,y,313+(i-wagNum/2)*147,323,141,60)) then + btnID = 10 + i + if not value then + self.Cam.Wagon = i + self.Cam.Page = self.Cam.Cameras[i].wagType == 1 and 7 or self.Cam.Cameras[i].wagType == 2 and 5 or 1 + newPage = true + end + end + end + end + + for i=1,#self.Buttons do + local btn = self.Buttons[i] + if btn.show(self.Cam.Page) and InRange(x,y,btn.x,btn.y,btn.w,btn.h) then + if not value and btn.touch then newPage = btn.touch(self) end + btnID = btn.id + end + end + + if newPage then + self.Cam.AutoOpen = false + for i=1,4 do + self.Cam[i].Link = CurTime()+math.Rand(0.2,1) + self.Cam[i].Ent = self.Cam.Cameras[self.Cam.Wagon][self.Cam.Page][i] + if i > #self.Cam.Cameras[self.Cam.Wagon][self.Cam.Page] then + self.Cam[i].Link = nil + self.Cam[i].Ent = NULL + end + end + self.Train:SetNW2Int("BMCIK:CamWagIndex",self.Cam.Wagon) + self.Train:SetNW2Int("BMCIK:CamType",self.Cam.Cameras[self.Cam.Wagon].wagType) + self.Train:SetNW2Int("BMCIK:CamWagNumber",self.Cam.Cameras[self.Cam.Wagon].wagNum) + end + + self.Train:SetNW2Int("BMCIK:IDTouched",btnID or 0) +end + +function TRAIN_SYSTEM:Trigger(name,value) + name = name:gsub("Sarmat","") + if name ~= "Up" and name ~= "Down" and not value then return end + local Train = self.Train + local annTbl = Metrostroi.SarmatUPOSetup[Train:GetNW2Int("Announcer")] + local Announcer = self.Announcer + local annState = Announcer.State + local selected = self:List_GetSelectedItem() + + if annState == 1 then + if name == "Up" or name == "Down" or name == "Enter" or name == "Start" then + Announcer.AVTDepart = false + end + end + + if annState == 12 and name == "Esc" then + if Announcer.PrevLimitStation ~= Announcer.LimitStation then + if Announcer.LimitStation then + self.List.States[1].Count = (Announcer.Path and (#annTbl[Announcer.Line] - Announcer.LimitStation + 1) or Announcer.LimitStation)*2 + local lastStation = Announcer.Station + if Announcer.Path then + Announcer.Station = math.max(Announcer.Station,Announcer.LimitStation) else - self.Station = math.max(self.StartStation,self.Station - 1) + Announcer.Station = math.min(Announcer.Station,Announcer.LimitStation) + end + if lastStation ~= Announcer.Station then + Announcer.OnStation = true end - self.Arrived = true else - if self.Station ~= (self.Path and self.EndStation or self.StartStation) then - self.Arrived = false - end + self.List.States[1].Count = #annTbl[Announcer.Line]*2 end - end - self.Last = self.Station == last - self.Depeating = false - self:UpdateSarmat() - end - - function TRAIN_SYSTEM:AnnQueue(msg) - local Announcer = self.Train.Announcer - if msg and type(msg) ~= "table" then - Announcer:Queue{msg} - else - Announcer:Queue(msg) + self:BMTS_Update() + Announcer.PrevLimitStation = nil end end - function TRAIN_SYSTEM:Play(dep) - local ltbl = Metrostroi.SarmatUPOSetup[self.Train:GetNW2Int("Announcer",1)][self.Line] - if not ltbl then return end - local stbl = ltbl[self.Station] - local last = (self.Path and not ltbl.Loop) and self.StartStation or self.EndStation - local lastst = self.Station == last - if dep then - local message = stbl.dep[self.Path and 2 or 1] - if message and not lastst then - self.Train.Announcer:TriggerInput("Reset","AnnouncementsSarmatUPO") - self:AnnQueue("tone") - if stbl.odz then self:AnnQueue(stbl.odz) end - self:AnnQueue(message) - end - else - local message - if lastst then - message = stbl.arrlast[self.Path and 2 or 1] - else - message = stbl.arr[self.Path and 2 or 1] - end - if message then - self.Train.Announcer:TriggerInput("Reset","AnnouncementsSarmatUPO") - self:AnnQueue("tone") - if lastst and not stbl.ignorelast then self:AnnQueue(-1) end - self:AnnQueue(message) - end - end - self.Last = lastst - self:UpdateSarmat() + if annState == 23 and Announcer.TrainTrain and (name == "Esc" or name == "Zero") then + Announcer.TrainTrain = false + return end - - function TRAIN_SYSTEM:UpdateSarmat() - if not self.Active then return end - local tbl = Metrostroi.SarmatUPOSetup[self.Train:GetNW2Int("Announcer",1)][self.Line] - if not tbl then - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"PassSchemes",nil,"Current",0) - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"PassSchemes",nil,"Arrival",32) - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"PassSchemes",nil,"Path",self.Path) - - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"Tickers",nil,"Prev",self.Specials[self.Line]) - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"Tickers",nil,"PrevEn",false) - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"Tickers",nil,"Next",self.Specials[self.Line]) - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"Tickers",nil,"NextEn",false) - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"Tickers",nil,"NextRight",false) - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"Tickers",nil,"Curr",self.Specials[self.Line]) - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"Tickers",nil,"CurrEn",false) - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"Tickers",nil,"CurrRight",false) - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"Tickers",nil,"Arrived",true) - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"Tickers",nil,"Last",false) - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"Tickers",nil,"Closing",false) - if self.Specials[self.Line] then - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"Tickers",nil,"Special","%g"..self.Specials[self.Line].."\n%r"..self.Specials[self.Line]) + + ---- ▲ + if name == "Up" then + if value then + self:List_Prev() + if annState == 1 then self:Announcer_Prev() end + if self.ListTimerDir == nil then + self.ListTimer = CurTime()+0.4 + self.ListTimerDir = false end - return - end - local stbl = tbl.LED - local last = self.Path and self.FirstStation or self.LastStation - - local curr=0 - if self.Path then - for i=#stbl,self.Station+(self.Depeating and 0 or 1),-1 do curr = curr + stbl[i] end else - for i=1,self.Station-(self.Depeating and 0 or 1) do curr = curr + stbl[i] end + self.ListTimer = nil + self.ListTimerDir = nil end - local nxt = 0 - if self.Arrived and not self.Depeating then - curr = curr + stbl[self.Station] + ---- ▼ + elseif name == "Down" then + if value then + self:List_Next() + if annState == 1 then self:Announcer_Next() end + if self.ListTimerDir == nil then + self.ListTimer = CurTime()+0.4 + self.ListTimerDir = true + end else - nxt = stbl[self.Station] + self.ListTimer = nil + self.ListTimerDir = nil end - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"PassSchemes",nil,"Current",curr) - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"PassSchemes",nil,"Arrival",nxt) - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"PassSchemes",nil,"Path",self.Path) - - local curr,prev,nxt = tbl[self.Station],tbl[self.Station-(self.Path and -1 or 1)],tbl[self.Station-(self.Path and 1 or -1)] - if not self.Arrived then prev = curr nxt = curr end - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"Tickers",nil,"Prev",prev and prev[2]) - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"Tickers",nil,"PrevEn",prev and prev[3]) - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"Tickers",nil,"Next",nxt and nxt[2]) - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"Tickers",nil,"NextEn",nxt and nxt[3]) - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"Tickers",nil,"NextRight",nxt and nxt.right_doors) - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"Tickers",nil,"Curr",curr and curr[2]) - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"Tickers",nil,"CurrEn",curr and curr[3]) - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"Tickers",nil,"CurrRight",curr and curr.right_doors) - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"Tickers",nil,"Arrived",self.Arrived and not self.Depeating) - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"Tickers",nil,"Last",self.Last) - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"Tickers",nil,"Closing",self.Depeating) - self.Train:CANWrite("Sarmat",self.Train:GetWagonNumber(),"Tickers",nil,"Special",not self.Last and (self.Arrived and (self.Depeating and curr.messagedep or not self.Depeating and curr.messagearr) or not self.Arrived and prev.messagedep)) - end - - function TRAIN_SYSTEM:Trigger(name,value) - local Train = self.Train - if self.SarmatAnnState == 1 then - if name == "SarmatZero" and value then - self:Zero() - if self.ZeroTimer then - if CurTime()-self.ZeroTimer < 0.3 then self.SarmatAnnState = 2 end - self.ZeroTimer = nil - end - if not self.ZeroTimer then self.ZeroTimer = CurTime() end + ---- Enter + elseif name == "Enter" then + if annState == 0 then return end + if annState == 1 then + self:Announcer_CabPlay() + elseif annState == 2 then + Announcer.PrevState2 = Announcer.PrevState + local sTbl = self[self.SettingsList[selected][2]] + self:Announcer_SetState(20+selected,sTbl and #sTbl or 1) + if selected == 5 then + local Cam = self.Cam + local videoSended = (Cam[1].Link==true or Cam[2].Link==true or Cam[3].Link==true or Cam[4].Link==true) and 1 or 0 + Train:SetNW2Int("BMCIK:AddInfoNIIPDoors",self.NIIP.DOORS_closed) + Train:SetNW2Int("BMCIK:AddInfoNIIPSpeed",self.NIIP.SPEED) + Train:SetNW2Int("BMCIK:AddInfoUPO",self.UPOActive) + Train:SetNW2Int("BMCIK:AddInfoVideo",videoSended) end - if name == "SarmatLine" and value then - self.LineEnabled = not self.LineEnabled - end - if name == "SarmatStart" and value and self.LineOut==0 then - if not self.Arrived then - self:Play(false) - elseif self.Arrived then - self:Play(true) - end - end - local stbl = Metrostroi.SarmatUPOSetup[self.Train:GetNW2Int("Announcer",1)] - if name == "SarmatPath" and value then - self.Path = not self.Path - if not stbl[self.Line] then - self.LastStationName = self.Specials[self.Line] - elseif self.EndStation == 0 then - self.LastStationName = "Кольцевой" + elseif annState > 10 and annState < 20 then + if annState == 12 then + local selLast = Announcer.LastStations[selected] + if Announcer.LimitStation == selLast then + Announcer.LimitStation = false else - self.LastStationName = stbl[self.Line][self.Path and not stbl[self.Line].Loop and self.StartStation or self.EndStation][2] + Announcer.LimitStation = selLast end - self:Zero() - end - if name == "SarmatF1" and value and stbl[self.Line] then - self.SarmatAnnState = 3 - self.Select = 1 - end - if name == "SarmatF2" and value and stbl[self.Line] then - self.SarmatAnnState = 4 - self.Select = 1 - end - if name == "SarmatF3" and value and stbl[self.Line] then - self.SarmatAnnState = 5 - self.Select = 1 - end - if name == "SarmatF4" and value then - self.SarmatAnnState = 6 - self.Select = 1 - end - if name == "SarmatDown" and value then - self:Next() - end - if name == "SarmatUp" and value then - self:Prev() - end - end - if self.SarmatAnnState == 2 then - local stbl = Metrostroi.SarmatUPOSetup[self.Train:GetNW2Int("Announcer",1)] - if name == "SarmatDown" and value then - self.Line = math.min(#stbl,self.Line + 1) - end - if name == "SarmatUp" and value then - self.Line = math.max(-4,self.Line - 1) - end - if name == "SarmatEnter" and value then - self.SarmatAnnState = 1 - self.StartStation = 1 - if stbl[self.Line] then - if stbl[self.Line].Loop then - self.EndStation = 0 - else - self.EndStation = #stbl[self.Line] - end - if self.EndStation == 0 then - self.LastStationName = "Кольцевой" - else - self.LastStationName = stbl[self.Line][self.Path and not stbl[self.Line].Loop and self.StartStation or self.EndStation][2] - end - else - self.EndStation = 0 - self.LastStationName = self.Specials[self.Line] + elseif annState == 15 then + if Announcer.Active and selected == Announcer.Line then + self:List_Load(1) + Announcer.State = 1 + return end - self:Zero() + Announcer.Line = selected + self:Announcer_Activate(true) end - end - if self.SarmatAnnState == 3 then - local stbl = Metrostroi.SarmatUPOSetup[self.Train:GetNW2Int("Announcer",1)] - local stbll = stbl[self.Line] - if name == "SarmatDown" and value then - for i=self.Select+1,#stbll do - if i==1 or i==#stbll or stbll[i].arrlast then - self.Select = i - break - end - end - end - if name == "SarmatUp" and value then - local selected = false - for i=self.Select-1,1,-1 do - if i==1 or i==#stbll or stbll[i].arrlast then - self.Select = i - selected = true - break - end - end - if stbll.Loop and not selected then - self.Select = 0 - end - end - if name == "SarmatF1" and value and not stbll.Loop then - if self.Select < self.EndStation then - self.StartStation = self.Select - self.LastStationName = stbl[self.Line][self.Path and not stbl[self.Line].Loop and self.StartStation or self.EndStation][2] - self:Zero() - end - end - if name == "SarmatF2" and value then - if self.Select > self.StartStation or stbll.Loop then - self.EndStation = self.Select - if self.EndStation == 0 then - self.LastStationName = "Кольцевой" - else - self.LastStationName = stbl[self.Line][self.Path and not stbl[self.Line].Loop and self.StartStation or self.EndStation][2] - end - self:Zero() - end - end - if (name == "SarmatEnter" or name == "SarmatEsc") and value then - self.SarmatAnnState = 1 - self:Zero() - end - end - if self.SarmatAnnState == 4 then - if (name == "SarmatEnter" or name == "SarmatEsc") and value then - self.SarmatAnnState = 1 - end - end - if self.SarmatAnnState == 5 then - if (name == "SarmatEnter" or name == "SarmatEsc") and value then - self.SarmatAnnState = 1 - end - end - if self.SarmatAnnState == 6 then - if (name == "SarmatEnter" or name == "SarmatEsc") and value then - self.SarmatAnnState = 1 - end - end - Train:SetNW2Int("SarmatSelect",self.Select) - end - function TRAIN_SYSTEM:Think(dT) - local Train = self.Train - local Power = Train.Electric.Power > 0 and Train.SF17.Value > 0 + elseif annState > 20 then + if annState == 22 then + Announcer.Mode = selected + elseif annState == 23 then + if not Announcer.TrainTrain then Announcer.TrainTrain = true end + elseif annState == 24 then + local selItem = self.AnnVolumeList[selected] + local volumes = self.Announcer.Volumes - if not Power and self.SarmatState ~= 0 then - self.SarmatState = 0 - self.SarmatTimer = nil - if self.LineOut>0 then self:AnnQueue(-2) end + volumes[selItem[2]] = volumes[selItem[2]] + 1 + if volumes[selItem[2]] > selItem[4] then volumes[selItem[2]] = selItem[3] end + + -- -- from 0 to N with a resolution of 10. The value of N can be calculated using the formula N = 100 - P, + -- -- where P - is the value of the volume level set in the line «Громкость инф. в салоне». + -- -- TODO: See how it works in 81-765 and do it by analogy + self.Train:CANWrite("BMCIK",nil,"BNT",nil,self.CAN_VOLUMES,{volumes.Salon,volumes.UPOSalon,volumes.V5}) + elseif annState == 28 then + Announcer.BITTime = selected == 2 + self.Train:CANWrite("BMCIK",nil,"BIT",nil,self.CAN_BITTIME,Announcer.BITTime) + end end - if Power and self.SarmatState == 0 then - self.SarmatState = -1 - self.SarmatTimer = CurTime()-math.Rand(-0.5,1) - self.SarmatAnnState = 1 - self.SarmatCamState = 1 - self.Cam1,self.Cam1E = false,NULL - self.Cam2,self.Cam2E = false,NULL - self.Cam3,self.Cam3E = false,NULL - self.Cam4,self.Cam4E = false,NULL - self.Selected = 0 - Train:SetNW2Int("SarmatCamSelected",self.Selected) - end - if self.SarmatState == -1 and self.SarmatTimer and CurTime()-self.SarmatTimer > 2 then - self.SarmatState = -2 - self.SarmatTimer = CurTime()-math.Rand(-0.5,1.5) - end - if self.SarmatState == -2 and self.SarmatTimer and CurTime()-self.SarmatTimer > 14 then - self.SarmatState = -3 - self.SarmatTimer = CurTime()-math.Rand(-0.3,0.5) - end - if self.SarmatState == -3 and self.SarmatTimer and CurTime()-self.SarmatTimer > 1 then - if Metrostroi.SarmatUPOSetup and Metrostroi.SarmatUPOSetup[self.Train:GetNW2Int("Announcer",1)] then - self.SarmatState = 1 - else - self.SarmatState = -4 + ---- Esc + elseif name == "Esc" then + if annState == 1 then + -- Single click delay + if not self.EscBtnTimer then + self.EscBtnTimer = CurTime() + 0.3 return end - local stbl = Metrostroi.SarmatUPOSetup[self.Train:GetNW2Int("Announcer",1)] - self.StartStation = self.StartStation or 1 - if stbl[self.Line].Loop then - self.EndStation = self.EndStation or 0 - else - self.EndStation = self.EndStation or #stbl[self.Line] - end - if self.EndStation == 0 then - self.LastStationName = "Кольцевой" - else - self.LastStationName = stbl[self.Line][self.Path and not stbl[self.Line].Loop and self.StartStation or self.EndStation][2] - end - self:Zero() + -- Double click + self.EscBtnTimer = nil + self:Announcer_SetState(14,1) + return end - if self.SarmatState > 0 and Train.BUKP.Active > 0 then - if self.SarmatCamState > 1 then - Train:SetNW2Int("SarmatCamType",self.SarmatCamType) - local cam1,cam2,cam3,cam4 = false,false,false,false - for i=1,#Train.WagonList do - local train = Train.WagonList[i] - if self.Cam1 and self.Cam1E == train then cam1 = true end - if self.Cam2 and self.Cam2E == train then cam2 = true end - if self.Cam3 and self.Cam3E == train then cam3 = true end - if self.Cam4 and self.Cam4E == train then cam4 = true end - end - if self.Cam1 == true and (not IsValid(self.Cam1E) or not cam1) then self.Cam1 = false end - if self.Cam2 == true and (not IsValid(self.Cam2E) or not cam2) then self.Cam2 = false end - if self.Cam3 == true and (not IsValid(self.Cam3E) or not cam3) then self.Cam3 = false end - if self.Cam4 == true and (not IsValid(self.Cam4E) or not cam4) then self.Cam4 = false end - if self.Cam1 == true then - Train:SetNW2Bool("SarmatCam1C",true) - Train:SetNW2Entity("SarmatCam1E",self.Cam1E) - else - if self.Cam1 and self.Cam1 ~= true and CurTime()-self.Cam1 > 0 then self.Cam1 = true end - Train:SetNW2Bool("SarmatCam1C",false) - end - if IsValid(self.Cam1E) then Train:SetNW2Int("SarmatCam1EN",self.Cam1E:GetWagonNumber()) end - if self.Cam2 == true then - Train:SetNW2Bool("SarmatCam2C",true) - Train:SetNW2Entity("SarmatCam2E",self.Cam2E) - else - if self.Cam2 and self.Cam2 ~= true and CurTime()-self.Cam2 > 0 then self.Cam2 = true end - Train:SetNW2Bool("SarmatCam2C",false) - end - if IsValid(self.Cam2E) then Train:SetNW2Int("SarmatCam2EN",self.Cam2E:GetWagonNumber()) end - if self.Cam3 == true then - Train:SetNW2Bool("SarmatCam3C",true) - Train:SetNW2Entity("SarmatCam3E",self.Cam3E) - else - if self.Cam3 and self.Cam3 ~= true and CurTime()-self.Cam3 > 0 then self.Cam3 = true end - Train:SetNW2Bool("SarmatCam3C",false) - end - if IsValid(self.Cam3E) then Train:SetNW2Int("SarmatCam3EN",self.Cam3E:GetWagonNumber()) end - if self.Cam4 == true then - Train:SetNW2Bool("SarmatCam4C",true) - Train:SetNW2Entity("SarmatCam4E",self.Cam4E) - else - if self.Cam4 and self.Cam4 ~= true and CurTime()-self.Cam4 > 0 then self.Cam4 = true end - Train:SetNW2Bool("SarmatCam4C",false) - end - if IsValid(self.Cam4E) then Train:SetNW2Int("SarmatCam4EN",self.Cam4E:GetWagonNumber()) end - Train:SetNW2Int("SarmatCamC",self.SarmatCamCount) - end - - - Train:SetNW2Int("SarmatCamState",self.SarmatCamState) - else - Train:SetNW2Int("SarmatCamState",0) - Train:SetNW2Bool("SarmatCam1C",false) - Train:SetNW2Bool("SarmatCam2C",false) - Train:SetNW2Bool("SarmatCam3C",false) - Train:SetNW2Bool("SarmatCam4C",false) + if not Announcer.PrevState then return end + self:List_Load(Announcer.PrevState) + Announcer.State = Announcer.PrevState + Announcer.PrevState = Announcer.PrevState2 + Announcer.PrevState2 = nil + ---- F1 + elseif name == "F1" then + if annState ~= 1 then return end + self:Announcer_SetState(11,1) + ---- F2 + elseif name == "F2" then + if annState ~= 1 then return end + Announcer.PrevLimitStation = Announcer.LimitStation + self:Announcer_SetState(12,#Announcer.LastStations) + ---- F3 + elseif name == "F3" then + if annState ~= 1 then return end + self:Announcer_SetState(13,1) + ---- F4 + elseif name == "F4" then + if annState > 1 then return end + self:Announcer_SetState(2,#self.SettingsList) + ---- ПУТЬ + elseif name == "Path" then + if Announcer.Line == 0 then return end + Announcer.PathSel = not Announcer.PathSel + --- >0< + elseif name == "Zero" then + if annState > 1 then return end + -- Single click delay + if not self.ZeroBtnTimer then + self.ZeroBtnTimer = CurTime() + 0.3 + return end - if self.SarmatState > 0 and Train.BUKP.Active > 0 then - if not self.Active then self.Active = true self:UpdateSarmat() end + + -- Double click + self.ZeroBtnTimer = nil + local prevClear = annState == 0 + if annTbl then self:Announcer_SetState(15,#annTbl) end + if prevClear then Announcer.PrevState = nil end + ---- ЛИНИЯ + elseif name == "Line" then + Announcer.LineEnabled = not Announcer.LineEnabled + ---- ПУСК + elseif name == "Start" then + if annState == 1 and Announcer.Mode == 3 then + self:Announcer_Play() + self:Announcer_Next() + self:List_Next() + -- if self:Announcer_Next(true) then + -- self:List_Set(1,1) + -- else + -- self:List_Next(1) + -- end + self:CANUpdate() + end + end +end + +function TRAIN_SYSTEM:Think(dT) + local Train = self.Train + + -- BMCIK-01 logic + local Power = Train.Electric.Power > 0 and (Train.SF16.Value + Train.SF17.Value) > 0 + if Power then + local Cam = self.Cam + local Announcer = self.Announcer + if self.State > 0 then + ---- Buttons -------------------- + local valBtn = false for k,v in pairs(self.TriggerNames) do - if Train[v] and (Train[v].Value > 0.5) ~= self.Triggers[v] then - self:Trigger(v,Train[v].Value > 0.5) - --print(v,self.Train[v].Value > 0.5) - self.Triggers[v] = Train[v].Value > 0.5 + valBtn = Train[v].Value > 0.5 + if Train[v] and (valBtn) ~= self.Triggers[v] then + self:Trigger(v,valBtn) + self.Triggers[v] = valBtn end end - local OpenDoors = Train.BUKP.OpenLeft or Train.BUKP.OpenRight - local CloseDoors = not not Train.BUKP.CloseRing - local UPOPlaying = self.UPOActive>0 and Train.UPO.LineOut>0 - if not self.Depeating and (OpenDoors or UPOPlaying) and not self.Arrived then - self.Arrived = true - if self.UPOActive==0 then self:Play(false) end - end - if OpenDoors and self.Depeating then - self.Depeating = false - self:UpdateSarmat() - end - if self.Arrived and (CloseDoors~=self.CloseDoors and CloseDoors or UPOPlaying) then - --local ltbl = Metrostroi.SarmatUPOSetup[self.Train:GetNW2Int("Announcer",1)][self.Line] - if self.UPOActive==0 and not self.Depeating then - self.Depeating = true - self:Play(true) + + if self.ZeroBtnTimer and CurTime() > self.ZeroBtnTimer then + self.ZeroBtnTimer = nil + if Announcer.State == 0 then + self:Announcer_Activate() + elseif Announcer.State == 1 then + self:Announcer_Zero() + local lTbl = Metrostroi.SarmatUPOSetup[Train:GetNW2Int("Announcer")][Announcer.Line] + local countSt = Announcer.LimitStation and (Announcer.Path and #lTbl - Announcer.LimitStation + 1 or Announcer.LimitStation) or #lTbl + self:List_Reset(countSt*2) end - --self:UpdateSarmat() end - self.CloseDoors = CloseDoors - if self.UPOActive>0 and not UPOPlaying and (not self.UPOLock or CurTime()-self.UPOLock)>0.5 then + + if self.EscBtnTimer and CurTime() > self.EscBtnTimer then + self.EscBtnTimer = nil + end + + ---- BUKP CAN ------------------- + if CurTime() > self.CAN_SU then + self.CAN_SU = CurTime()+0.1 + + local BUKP = Train.BUKP + local niipSpeed = math.floor(BUKP.Speed) + if self.NIIP.SPEED ~= niipSpeed then + Train:CANWrite("BMCIK",nil,"BNT",nil,self.CAN_SPEED,niipSpeed) + self.NIIP.SPEED = niipSpeed + end + self.NIIP.DOORS_closed = BUKP.LSD and 1 or 0 + + local cabAcitve = Train.Electric.CabActive + if self.NIIP.CabActive ~= cabAcitve then + if cabAcitve > 0 then -- ПГК + self:Announcer_Activate() + end + self.NIIP.CabActive = cabAcitve + end + end + + ---- Cameras -------------------- + if Cam.Page > 0 then + local wags = {false,false,false,false} + local wagList = Train.WagonList + for i=1,Cam.WagNum do + local iWag = wagList[i] + if Cam[1].Link and Cam[1].Ent == iWag then wags[1] = true end + if Cam[2].Link and Cam[2].Ent == iWag then wags[2] = true end + if Cam[3].Link and Cam[3].Ent == iWag then wags[3] = true end + if Cam[4].Link and Cam[4].Ent == iWag then wags[4] = true end + end + + local camC = 0 + for i=1,4 do + local iCam = Cam[i] + if iCam.Link == true then + Train:SetNW2Entity("BMCIK:CamE"..i,iCam.Ent) + if not wags[i] or iCam.Ent.Electric.Power < 1 then + iCam.Link = false + end + else + if iCam.Link and CurTime() > iCam.Link then + iCam.Link = wags[i] + end + end + camC = setBitValue(camC,iCam.Link==true and 1 or 0,i-1,1) + end + camC = setBitValue(camC,Cam.Fullscreen,4,3) + Train:SetNW2Int("BMCIK:Cam",camC) + + if Cam.AutoOpen then + Cam.Distance = Cam.Distance + self.NIIP.SPEED*dT/3.6 + if Cam.Distance > Cam.TrainLen then + self:Cam_Close() + Cam.AutoOpen = nil + Cam.Distance = nil + end + end + end + Train:SetNW2Int("BMCIK:CamPage",Cam.Page) + + ---- Announcer ------------------ + local annPlaying = Train:GetNW2Bool("AnnouncerPlaying") + if Announcer.State > 0 then + if Announcer.Active then + if Announcer.AVTDepart then + if self.NIIP.SPEED > 3 then + if self:Announcer_Next(true) then + self:List_Set(1,1) + else + self:List_Next(1) + end + + Announcer.AVTDepart = false + end + end + + if Announcer.CabPlay and not annPlaying and #Train.Announcer.Schedule == 0 then + self:Announcer_CabStop() + end + + self.LineOut = (Train.Announcer.AnnTable=="AnnouncementsSarmatUPO" and annPlaying) and 1 or 0 + self.UPOActive = Announcer.Mode > 1 and 1 or 0 + if self.UPOActive > 0 then + Announcer.UPOLock = Train.UPO.LineOut > 0 + end + + Train:SetNW2Int("BMCIK:VolCab",Announcer.UPOLock and Announcer.Volumes.UPOCabin or Announcer.Volumes.Cabin) + else + if Announcer.State == 1 or (Announcer.State > 10 and Announcer.State < 20 and Announcer.State ~= 15) then + self:Announcer_Stop() + Train:SetNW2Int("BMCIK:VolCab",0) + Announcer.State = 0 + end + end + + if self.ListTimer and CurTime() > self.ListTimer then + if self.ListTimerDir then + self:List_Next() + if Announcer.State == 1 then self:Announcer_Next() end + else + self:List_Prev() + if Announcer.State == 1 then self:Announcer_Prev() end + end + self.ListTimer = CurTime()+0.2 + end + + if Announcer.State > 20 then + if Announcer.State == 22 then + Train:SetNW2Int("BMCIK:AnnMode",Announcer.Mode) + elseif Announcer.State == 23 then + Train:SetNW2Bool("BMCIK:TrainTrain",Announcer.TrainTrain) + elseif Announcer.State == 24 then + local volumes = 0 + local annVolumes = Announcer.Volumes + volumes = setBitValue(volumes,annVolumes.Cabin,0,4) + volumes = setBitValue(volumes,annVolumes.Salon,4,4) + volumes = setBitValue(volumes,annVolumes.UPOCabin,8,4) + volumes = setBitValue(volumes,annVolumes.UPOSalon,12,4) + volumes = setBitValue(volumes,annVolumes.EmerCab,16,4) + volumes = setBitValue(volumes,annVolumes.V5,20,4) + Train:SetNW2Int("BMCIK:VolumesPage",volumes) + elseif Announcer.State == 28 then + Train:SetNW2Bool("BMCIK:BITTime",Announcer.BITTime) + end + end + + Train:SetNW2Int("BMCIK:ListSelect",self.List.Selected) + Train:SetNW2Int("BMCIK:ListOffset",self.List.Offset) + else + Announcer.Active = false + self.LineOut = annPlaying and 1 or 0 self.UPOActive = 0 - self.UPOLock = false end - if self.Depeating and Train.BUKP.Speed>3 then - self:Next() + + local cikState = 0 + if Train.Microphone.Value > 0 then + if Announcer.LineEnabled then + cikState = 3 -- Громкая связь + else + cikState = 2 -- Межкабинная связь активна + end + elseif self.LineOut + Train.UPO.LineOut > 0 then + cikState = 1 -- Воспроизведение... + else + cikState = 0 -- Готов end + if Announcer.CIKStateIntercab then + cikState = Announcer.CIKStateIntercab + end + + if Announcer.CIKState ~= cikState then + if not Announcer.CIKStateIntercab then + Train:CANWrite("BMCIK",Train:GetWagonNumber(),"BMCIK",nil,self.CAN_CIKSTATE,cikState > 1 and cikState or nil) + end + + if Announcer.Active and cikState == 3 and self.LineOut then self:Announcer_Stop() end + Announcer.CIKState = cikState + end + + local ann = 0 + ann = setBitValue(ann,Announcer.State,0,6) + ann = setBitValue(ann,Announcer.CIKState,6,4) + ann = setBitValue(ann,Announcer.Line,10,8) + ann = setBitValue(ann,Announcer.LimitStation or 0,18,12) + ann = setBitValue(ann,Announcer.Path and 1 or 0,30,1) + ann = setBitValue(ann,Announcer.PathSel and 1 or 0,31,1) + Train:SetNW2Int("BMCIK:Announcer",ann) + Train:SetNW2Bool("BMCIK:LineEnabled",Announcer.LineEnabled) + elseif self.State < 0 then + if CurTime() > self.LoadingTimer then + if self.State == -6 then + self.State = -5 + self.LoadingTimer = CurTime()+math.Rand(0.9,1.5) + elseif self.State == -5 then + self.State = -4 + self.LoadingTimer = CurTime()+2 + elseif self.State == -4 then + self.State = -3 + self.LoadingTimer = CurTime()+math.Rand(9,12) + elseif self.State == -3 then + self.State = -2 + self.LoadingTimer = CurTime()+math.Rand(1,3) + elseif self.State == -2 then + self.State = -1 + self.LoadingTimer = CurTime()+math.Rand(2,3) + elseif self.State == -1 then + self.State = 1 + self.CAN_SU = CurTime() + self:Cam_Scan() + end + end + if self.State == -4 then Train:SetNW2Int("BMCIK:GRUBTimeout",self.LoadingTimer - CurTime() + 1) end else - if self.Depeating then - self:Next() - end - self.UPOActive = 0 - self.UPOLock = false - self.CloseDoors = false - self.Active = false - --self.CloseTimer = CurTime() + self.State = -6 + self.LoadingTimer = CurTime()+math.Rand(5,7) + -- self.State = -2 + -- self.LoadingTimer = CurTime()+3 + end + else + if self.State ~= 0 then + self:MemReset() + self.State = 0 end - Train:SetNW2Bool("SarmatMonitor",Train.Electric.Power>0 and Train.SF16.Value > 0) - Train:SetNW2Int("SarmatState",self.SarmatState) - Train:SetNW2Int("WagNum",#Train.WagonList) - - Train:SetNW2Int("SarmatAnnState",self.SarmatAnnState) - - Train:SetNW2Int("SarmatLine",self.Line) - Train:SetNW2Bool("SarmatPath",self.Path) - Train:SetNW2Int("SarmatStation",self.Station) - Train:SetNW2Bool("SarmatStationArr",self.Arrived) - - Train:SetNW2Bool("SarmatLineEnabled",self.LineEnabled) - - Train:SetNW2Int("SarmatStartStation",self.StartStation) - Train:SetNW2Int("SarmatEndStation",self.EndStation) - - local Ann = Train.Announcer - self.LineOut = (Ann.AnnTable=="AnnouncementsSarmatUPO" and Ann.AnnounceTimer) and 1 or 0 end -else - local function createFont(name,font,size,weight) - surface.CreateFont("Metrostroi_"..name, { - font = font, - size = size, - weight = weight or 400, - blursize = 0, - antialias = true, - underline = false, - italic = false, - strikeout = false, - symbol = false, - rotary = false, - shadow = false, - additive = false, - outline = false, - extended = true, - }) - end - --createFont("BUKPSpeed","Eurostar Metrostroi",80) - createFont("Arial15","Arial",15,800) - createFont("Arial20","Arial",20,800) - createFont("Arial22","Arial",22,400) - createFont("Arial25","Arial",25,400) - createFont("Arial30","Arial",30,400) - local ubuntu_load = surface.GetTextureID("models/metrostroi_train/81-722/screens/sarmat_upo/ubuntu_load") - local button = surface.GetTextureID("models/metrostroi_train/81-722/screens/sarmat_upo/button") - - - function TRAIN_SYSTEM:ClientInitialize() - self.Cam1 = self.Train:CreateRT("720SarmatC1",256,256,true) - self.Cam2 = self.Train:CreateRT("720SarmatC2",256,256,true) - self.Cam3 = self.Train:CreateRT("720SarmatC3",256,256,true) - self.Cam4 = self.Train:CreateRT("720SarmatC4",256,256,true) - end - local CamRT = surface.GetTextureID( "pp/rt" ) - local CamRTM = Material( "pp/rt" ) - local SarPos = Vector(470,41,-6) - function TRAIN_SYSTEM:ClientThink() - if not self.Train:ShouldDrawPanel("Sarmat") then return end - local train = self.Train - local state = train:GetNW2Int("SarmatState",0) - local camstate = train:GetNW2Int("SarmatCamState",1) - local Cam1,Cam1E = train:GetNW2Bool("SarmatCam1C"),train:GetNW2Entity("SarmatCam1E") - local Cam2,Cam2E = train:GetNW2Bool("SarmatCam2C"),train:GetNW2Entity("SarmatCam2E") - local Cam3,Cam3E = train:GetNW2Bool("SarmatCam3C"),train:GetNW2Entity("SarmatCam3E") - local Cam4,Cam4E = train:GetNW2Bool("SarmatCam4C"),train:GetNW2Entity("SarmatCam4E") - if state > 0 then - if camstate == 2 then - if Cam1 then Metrostroi.RenderCamOnRT(train,SarPos,"Cam1",math.Rand(0.2,0.5),self.Cam1,Cam1E,Vector(425,65,40),Angle(5,180-5,0),256,256,2,64,64) end - if Cam2 then Metrostroi.RenderCamOnRT(train,SarPos,"Cam2",math.Rand(0.2,0.5),self.Cam2,Cam2E,Vector(425,-65,40),Angle(5,180+5,0),256,256,2,64,64) end - end - if camstate == 3 then - if Cam1 then Metrostroi.RenderCamOnRT(train,SarPos,"Cam1",math.Rand(0.2,0.5),self.Cam1,Cam1E,Vector(425,-65,40),Angle(5,180+5,0),256,256,2,64,64) end - if Cam2 then Metrostroi.RenderCamOnRT(train,SarPos,"Cam2",math.Rand(0.2,0.5),self.Cam2,Cam2E,Vector(425,65,40),Angle(5,180-5,0),256,256,2,64,64) end - end - if camstate == 4 then - if Cam1 then Metrostroi.RenderCamOnRT(train,SarPos,"Cam1",math.Rand(0.2,0.5),self.Cam1,Cam1E,Vector(425,65,40),Angle(5,180-5,0),256,256,2,64,64) end - if Cam2 then Metrostroi.RenderCamOnRT(train,SarPos,"Cam2",math.Rand(0.2,0.5),self.Cam2,Cam2E,Vector(425,-65,40),Angle(5,180+5,0),256,256,2,64,64) end - if Cam3 then Metrostroi.RenderCamOnRT(train,SarPos,"Cam3",math.Rand(0.2,0.5),self.Cam3,Cam3E,Vector(425,-65,40),Angle(5,180+5,0),256,256,2,64,64) end - if Cam4 then Metrostroi.RenderCamOnRT(train,SarPos,"Cam4",math.Rand(0.2,0.5),self.Cam4,Cam4E,Vector(425,65,40),Angle(5,180-5,0),256,256,2,64,64) end - end - if camstate == 5 then - if Cam1 then Metrostroi.RenderCamOnRT(train,SarPos,"Cam1",math.Rand(0.2,0.5),self.Cam1,Cam1E,Vector(360,-45,30),Angle(15,180-15,0),256,256,1) end - if Cam2 then Metrostroi.RenderCamOnRT(train,SarPos,"Cam2",math.Rand(0.2,0.5),self.Cam2,Cam2E,Vector(360,45,30),Angle(15,180+15,0),256,256,1) end - if Cam3 then Metrostroi.RenderCamOnRT(train,SarPos,"Cam3",math.Rand(0.2,0.5),self.Cam3,Cam3E,Vector(-360,-45,30),Angle(15,15,0),256,256) end - if Cam4 then Metrostroi.RenderCamOnRT(train,SarPos,"Cam4",math.Rand(0.2,0.5),self.Cam4,Cam4E,Vector(-360,45,30),Angle(15,-15,0),256,256) end - end - if camstate == 6 then - if Cam1 then Metrostroi.RenderCamOnRT(train,SarPos,"Cam1",math.Rand(0.2,0.5),self.Cam1,Cam1E,Vector(408,35,37),Angle(25,-15,0),256,256,1) end - end - if camstate == 7 then - if Cam1 then Metrostroi.RenderCamOnRT(train,SarPos,"Cam1",math.Rand(0.2,0.5),self.Cam1,Cam1E,Vector(490,6,-7),Angle(0,0,0),256,256,1) end + -- BMTS-07 logic + local BMTSPower = Train.Electric.Power > 0 and Train.SF18.Value > 0 + local BMTS = self.BMTS + if BMTSPower and Train.SF18.Value > 0 then + if BMTS.State == 0 then + BMTS.State = -1 + BMTS.Loading = CurTime()+5 + BMTS.Update = true + elseif self.BMTS.State == -1 then + if CurTime() > BMTS.Loading then + BMTS.State = 1 + BMTS.Text = "" + BMTS.Loading = nil + BMTS.Update = true end end - --debugoverlay.Sphere(self.Train:LocalToWorld(Vector(425,-65,46)),2,1,Color( 255, 255, 255 ),true) - render.PushRenderTarget(self.Train.Sarmat,0,0,1024, 1024) + else + if BMTS.State ~= 0 then + BMTS.State = 0 + BMTS.Text = "" + BMTS.Update = true + end + end + + Train:SetNW2Int("BMCIK:State",self.State) + if BMTS.Update then + BMTS.Update = false + Train:SetNW2Int("BMTS:State",BMTS.State) + Train:SetNW2String("BMTS:Text",BMTS.Text) + end +end + +function TRAIN_SYSTEM:MemReset(resetAnn) + self.ZeroBtnTimer = nil + self.EscBtnTimer = nil + self.Brightness = 1 + + self.NIIP.CabActive = false + + self:Cam_Reset() + self:Announcer_Reset(resetAnn) + self:List_Reset() + + self.Train:SetNW2Int("BMCIK:IDTouched",0) + self.Train:SetNW2Float("BMCIK:Brightness",1) + self.Train:SetNW2Int("BMCIK:VolCab",0) +end + +if SERVER then return end + +local font20 = "Metrostroi_Dejavu20" +local font21 = "Metrostroi_Dejavu21" +local font28 = "Metrostroi_Dejavu28" + +-- Create fonts +local function createFont(name,font,size,weight,noAA) + surface.CreateFont("Metrostroi_"..name, { + font = font, + size = size, + weight = weight or 400, + blursize = 0, + antialias = not noAA, + underline = false, + italic = false, + strikeout = false, + symbol = false, + rotary = false, + shadow = false, + additive = false, + outline = false, + extended = true, + }) +end +createFont("Dejavu20","Dejavu Sans",20) +createFont("Dejavu21","Dejavu Sans",21) +createFont("Dejavu22","Dejavu Sans",22) +createFont("Dejavu26","Dejavu Sans",26) +createFont("Dejavu28","Dejavu Sans",28) +createFont("BMTS1","Arial",14,800,true) +createFont("BMTS2","Arial",17,800,true) +createFont("BMTS3","Arial",22,800,true) +createFont("BMTS4","Arial",30,800,true) + +local function drawText(text,x,y,xalign,yalign) + if (xalign or yalign) then + local w,h = surface.GetTextSize( text ) + if (xalign == TEXT_ALIGN_CENTER) then + x = x - w / 2 + elseif (xalign == TEXT_ALIGN_RIGHT) then + x = x - w + end + + if (yalign == TEXT_ALIGN_CENTER) then + y = y - h / 2 + elseif (yalign == TEXT_ALIGN_BOTTOM) then + y = y - h + end + end + surface.SetTextPos(x,y) + surface.DrawText(text) +end + +local scx,scy = 1,1 -- Multipliers for fix RT draw on screen +function TRAIN_SYSTEM:ClientInitialize() + scx,scy = math.max(ScrW()/2048,1),math.max(ScrH()/1024,1) + self.Cams = { + {self.Train:CreateRT("722BVK1",512,512),0}, + {self.Train:CreateRT("722BVK2",512,512),0}, + {self.Train:CreateRT("722BVK3",512,512),0}, + {self.Train:CreateRT("722BVK4",512,512),0} + } + + self.HeaderNames = table.Copy(self.HeaderNames) + self.List = { + Selected = 0, + Offset = 0 + } + self.BMTS = { + State = 0, + Text = "", + Update = true + } +end + +local BMTSPixels = surface.GetTextureID("models/metrostroi_train/81-722/screens/sarmat_upo/bmts") +function TRAIN_SYSTEM:ClientThink(dT) + -- БМЦИК-01 ЦИКВ.465122.049 + if self.Train:ShouldDrawPanel("BMCIK") then + render.PushRenderTarget(self.Train.BMCIKScr,0,0,2048, 1024) render.Clear(0, 0, 0, 0) cam.Start2D() + render.SetScissorRect(0,0,1280,800,true) surface.SetDrawColor(0,0,0) - surface.DrawRect(0,0,1024,640) - self:SarmatMonitor(self.Train) + surface.DrawRect(0,0,1280,800) + local state = self.Train:GetNW2Int("BMCIK:State",0) + self:BMCIK01(self.Train,state) + if state ~= 0 then + surface.SetDrawColor(20,20,90,8) + surface.DrawRect(0,0,1280,800) + end + render.SetScissorRect(0,0,0,0,false) cam.End2D() render.PopRenderTarget() end - local function drawButton(x,y,w,h,text) - surface.DrawTexturedRectRotated(x,y,w,h,0) - draw.SimpleText(text,"Metrostroi_Arial20",x,y, Color(200,200,200),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - end - local names = { - "Левые камеры", - "Передние камеры", - "Все левые/правые камеры", - "Задние камеры", - "Правые камеры", - "Салонные камеры", - "Камера на посте машиниста", - "Камера на посте машиниста", - "Путевая камера", - "Путевая камера", - } - local types = { - {"Левая камера 1 вагона","Левая камера %d вагона"}, - {"Левая камера 1 вагона","Правая камера 1 вагона"}, - {"Левая камера 1 вагона","Правая камера 1 вагона","Левая камера %d вагона","Правая камера %d вагона"}, - {"Левая камера %d вагона","Правая камера %d вагона"}, - {"Правая камера 1 вагона","Правая камера %d вагона"}, - {"Передняя правая камера салона","Передняя левая камера салона","Задняя правая камера салона","Задняя левая камера салона"}, - {"Камера кабины 1 вагона"}, - {"Камера кабины %d вагона"}, - {"Путевая камера 1 вагона"}, - {"Путевая камера %d вагона"}, - } - local inverts = { - {true,false}, - {true,true}, - {true,true,false,false}, - {false,false}, - {true,false}, - {true,true,false,false}, - {false}, - {false}, - {false}, - {false}, - } - --SarmatCam2T - function TRAIN_SYSTEM:SarmatMonitor(Train) - local state = Train:GetNW2Int("SarmatState",0) - local annstate = Train:GetNW2Int("SarmatAnnState",1) - local camstate = Train:GetNW2Int("SarmatCamState",1) - local WagNum = Train:GetNW2Int("WagNum",0) - if not Train:GetNW2Bool("SarmatMonitor") then return end - if state == -2 then - surface.SetDrawColor(255,255,255) - surface.DrawRect(0,0,1024,640) - surface.SetDrawColor(220,83,13) - surface.DrawRect(450+math.ceil(CurTime()%4-1)*32,341,6,6) - surface.SetTexture(ubuntu_load) - surface.SetDrawColor(255,255,255) - surface.DrawTexturedRectRotated(512,512,1024,1024,0) - elseif state == 1 then - surface.SetDrawColor(15,15,15) - surface.DrawRect(0,0,1024,640) - - local line = Train:GetNW2Int("SarmatLine") - local path = Train:GetNW2Bool("SarmatPath") - local station = Train:GetNW2Int("SarmatStation",1) - local stationarr = Train:GetNW2Bool("SarmatStationArr") - - local st = Train:GetNW2Int("SarmatStartStation") - local en = Train:GetNW2Int("SarmatEndStation") - - local lineenabled = Train:GetNW2Bool("SarmatLineEnabled") - local sel = Train:GetNW2Int("SarmatSelect",1) - local stbl = Metrostroi.SarmatUPOSetup[Train:GetNW2Int("Announcer",1)] - Metrostroi.DrawRectOutline(820,5,96,26,lineenabled and Color(0,200,0) or Color(50,50,50),3) - draw.SimpleText("ЛИНИЯ","Metrostroi_Arial15",868,17, lineenabled and Color(0,200,0) or Color(50,50,50),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - Metrostroi.DrawRectOutline(916,5,96,26,Color(200,200,200),3) - draw.SimpleText("ПУТЬ "..(path and 2 or 1),"Metrostroi_Arial15",964,17, Color(200,200,200),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - - if annstate == 1 then - local ann = stbl[line] - - - --render.DrawTextureToScreenRect(self.Cam3,0,260,260,260) - --render.DrawTextureToScreenRect(self.Cam4,260,260,260,260) - if not ann then - draw.SimpleText(Format("Линия: -%s-",self.Specials[line]),"Metrostroi_Arial20",870,60, Color(200,200,200),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - else - draw.SimpleText(Format("Линия: %s-%s%s",ann[1][2],ann[#ann][2],ann.Loop and "[кол]" or ""),"Metrostroi_Arial20",870,60, Color(200,200,200),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - local count = stationarr and 0.5 or 1 - local last - if ann.Loop then - last = path and station-16 or 16+station - else - last = (path and st or en) - end - for i=station,last,path and -1 or 1 do - i = (i-1)%(#ann)+1 - local stat = ann[i] - if ann.Loop and en > 0 and count > 1 and i == en+(path and -1 or 1) then - break - end - if ann.Loop or (path and i < station or i > station) or not stationarr then - if count > 9 and stationarr then - draw.SimpleText("...","Metrostroi_Arial22",760,30+count*54, Color(200,200,200),TEXT_ALIGN_LEFT,TEXT_ALIGN_CENTER) - break - elseif count >= 1 then - draw.SimpleText(stat[2],"Metrostroi_Arial22",760,30+count*54, Color(200,200,200),TEXT_ALIGN_LEFT,TEXT_ALIGN_CENTER) - end - end - if count > 8 and not stationarr then - draw.SimpleText("...","Metrostroi_Arial22",760,57+count*54, Color(200,200,200),TEXT_ALIGN_LEFT,TEXT_ALIGN_CENTER) - break - end - if (path and not ann.Loop and i~=st or (not path or ann.Loop and en > 0) and i~=en or ann.Loop and en == 0) then - draw.SimpleText(stat[2].." отпр.","Metrostroi_Arial22",760,57+count*54, Color(200,200,200),TEXT_ALIGN_LEFT,TEXT_ALIGN_CENTER) - else - draw.SimpleText(stat[2].." кон.","Metrostroi_Arial22",760,57+count*54, Color(200,200,200),TEXT_ALIGN_LEFT,TEXT_ALIGN_CENTER) - end - count = count + 1 - end - end - end - if annstate == 2 then - draw.SimpleText("Выбор линии:","Metrostroi_Arial20",870,60, Color(200,200,200),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - - for cline=-4,#stbl do - if cline>0 then - local ann = stbl[cline] - draw.SimpleText(Format("%s-%s%s",ann[1][2],ann[#ann][2],ann.Loop and "[кол]" or ""),"Metrostroi_Arial22",760,60+(cline+5)*30, cline == line and Color(80,120,150) or Color(200,200,200),TEXT_ALIGN_LEFT,TEXT_ALIGN_CENTER) - else - draw.SimpleText(Format("-%s-",self.Specials[cline]),"Metrostroi_Arial22",760,60+(cline+5)*30, cline == line and Color(80,120,150) or Color(200,200,200),TEXT_ALIGN_LEFT,TEXT_ALIGN_CENTER) - end - end - end - if annstate == 3 then - draw.SimpleText("Выбор начальной и конечной:","Metrostroi_Arial20",870,60, Color(200,200,200),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - local count = stbl[line].Loop and 2 or 1 - if stbl[line].Loop then - draw.SimpleText("Кольцевой","Metrostroi_Arial22",760,60+30, 0 == sel and Color(80,120,150) or Color(200,200,200),TEXT_ALIGN_LEFT,TEXT_ALIGN_CENTER) - if en == 0 then - draw.SimpleText("К","Metrostroi_Arial22",750,60+30, Color(200,0,0),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - end - end - for i=1,#stbl[line] do - local ann = stbl[line][i] - if i==1 or i==#stbl[line] or ann.arrlast then - draw.SimpleText(ann[2],"Metrostroi_Arial22",760,60+count*30, i == sel and Color(80,120,150) or Color(200,200,200),TEXT_ALIGN_LEFT,TEXT_ALIGN_CENTER) - if not stbl[line].Loop and st==i then - draw.SimpleText("Н","Metrostroi_Arial22",750,60+count*30, Color(0,200,0),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - elseif en == i then - draw.SimpleText("К","Metrostroi_Arial22",750,60+count*30, Color(200,0,0),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - end - count = count + 1 - end - end - end - - surface.SetDrawColor(127,127,127) - surface.SetTexture(button) - if camstate == 0 then - draw.SimpleText("Система видеонаблюдения","Metrostroi_Arial25",360 ,25, Color(200,200,200),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - draw.SimpleText("Не активна","Metrostroi_Arial20",360,85, Color(200,200,200),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - end - if camstate == 1 then - local selected = Train:GetNW2Int("SarmatCamSelected",0) - draw.SimpleText("Система видеонаблюдения","Metrostroi_Arial25",360 ,25, Color(200,200,200),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - draw.SimpleText("Наружные камеры","Metrostroi_Arial20",360,85, Color(200,200,200),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - - drawButton(124,140,113,40,"Левые") - draw.SimpleText("Вагон 1","Metrostroi_Arial20",235,106, Color(200,200,200),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - drawButton(242,140,113,40,"Передние") - draw.SimpleText("Все вагоны","Metrostroi_Arial20",360,106, Color(200,200,200),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - drawButton(360,140,113,40,"Вокруг") - draw.SimpleText("Вагон "..WagNum,"Metrostroi_Arial20",485,106, Color(200,200,200),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - drawButton(478,140,113,40,"Задние") - drawButton(596,140,113,40,"Правые") - - draw.SimpleText("Камеры в салоне","Metrostroi_Arial20",360,200, Color(200,200,200),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - for i=1+selected,math.min(WagNum,6+selected) do - drawButton(65+(i-1-selected)*118+118*math.max(0,6-WagNum)/2 ,235,113,40,"Вагон "..i) - end - - draw.SimpleText("Камеры на постах машиниста","Metrostroi_Arial20",360,315, Color(200,200,200),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - drawButton(220,350,113,40,"Вагон 1") - drawButton(500,350,113,40,"Вагон "..WagNum) - - draw.SimpleText("Путевые камеры","Metrostroi_Arial20",360,430, Color(200,200,200),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - drawButton(220,465,113,40,"Вагон 1") - drawButton(500,465,113,40,"Вагон "..WagNum) - --surface.DrawTexturedRectRotated(110,590,200,40,0) - --draw.SimpleText("Esc","Metrostroi_Arial20",110,590, Color(200,200,200),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - - if selected ~= 0 then drawButton(320,590,200,40,"<-") end - if 6+selected < WagNum then drawButton(530,590,200,40,"->") end - --render.DrawTextureToScreenRect(self.Cam1,15,50,690,510) - end - if camstate > 1 then - local camtype = Train:GetNW2Int("SarmatCamType") - draw.SimpleText(names[camtype] or "Система видеонаблюдения","Metrostroi_Arial25",15 ,25, Color(200,200,200),TEXT_ALIGN_LEFT,TEXT_ALIGN_CENTER) - local CamCount = Train:GetNW2Int("SarmatCamC") - local Cam1 = Train:GetNW2Bool("SarmatCam1C") - local Cam2 = Train:GetNW2Bool("SarmatCam2C") - local Cam3 = Train:GetNW2Bool("SarmatCam3C") - local Cam4 = Train:GetNW2Bool("SarmatCam4C") - if CamCount > 0 then - local invert = inverts[camtype][1] - local w,h = 340,250 - if CamCount < 2 then w = 690 end - if CamCount < 3 then h = 510 end - if Cam1 then - surface.SetDrawColor(255,255,255,255) - if invert then render.DrawTextureToScreenRect(self.Cam1,15+w,50,-w,h) else render.DrawTextureToScreenRect(self.Cam1,15,50,w,h) end - draw.SimpleText("связь","Metrostroi_Arial20",15+w-5,50+h-10, Color(50,200,50),TEXT_ALIGN_RIGHT,TEXT_ALIGN_CENTER) - else - surface.SetDrawColor(0,0,0,255) - surface.DrawRect(15,50,w,h) - draw.SimpleText("Подключение к камере...","Metrostroi_Arial30",15+w/2,50+h/2, Color(200,200,200),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - draw.SimpleText("нет связи","Metrostroi_Arial20",15+w-5,50+h-10, Color(200,50,50),TEXT_ALIGN_RIGHT,TEXT_ALIGN_CENTER) - end - draw.SimpleText("[1]"..Format(types[camtype][1],WagNum),"Metrostroi_Arial20",15+5,50+10, Color(200,150,50),TEXT_ALIGN_LEFT,TEXT_ALIGN_CENTER) - draw.SimpleText(Format("Вагон №%d",Train:GetNW2Int("SarmatCam1EN")),"Metrostroi_Arial20",15+5,50+30, Color(200,150,50),TEXT_ALIGN_LEFT,TEXT_ALIGN_CENTER) - Metrostroi.DrawRectOutline(15,50,w,h,Color(40,40,40),2) - end - if CamCount > 1 then - local h = 250 - if CamCount < 3 then h = 510 end - if Cam2 then - local invert = inverts[camtype][2] - surface.SetDrawColor(255,255,255,255) - if invert then render.DrawTextureToScreenRect(self.Cam2,340+15+10+340,50,-340,h) else render.DrawTextureToScreenRect(self.Cam2,340+15+10,50,340,h) end - draw.SimpleText("связь","Metrostroi_Arial20",365+340-5,50+h-10, Color(50,200,50),TEXT_ALIGN_RIGHT,TEXT_ALIGN_CENTER) - else - surface.SetDrawColor(0,0,0,255) - surface.DrawRect(340+15+10,50,340,h) - draw.SimpleText("Подключение к камере...","Metrostroi_Arial30",365+340/2,50+h/2, Color(200,200,200),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - draw.SimpleText("нет связи","Metrostroi_Arial20",365+340-5,50+h-10, Color(200,50,50),TEXT_ALIGN_RIGHT,TEXT_ALIGN_CENTER) - end - draw.SimpleText("[2]"..Format(types[camtype][2],WagNum),"Metrostroi_Arial20",365+5,50+10, Color(200,150,50),TEXT_ALIGN_LEFT,TEXT_ALIGN_CENTER) - draw.SimpleText(Format("Вагон №%d",Train:GetNW2Int("SarmatCam2EN")),"Metrostroi_Arial20",365+5,50+30, Color(200,150,50),TEXT_ALIGN_LEFT,TEXT_ALIGN_CENTER) - Metrostroi.DrawRectOutline(340+15+10,50,340,h,Color(40,40,40),2) - end - if CamCount > 2 then - if Cam3 then - local invert = inverts[camtype][3] - surface.SetDrawColor(255,255,255,255) - if invert then render.DrawTextureToScreenRect(self.Cam3,15+340,50+250+10,-340,250) else render.DrawTextureToScreenRect(self.Cam3,15,50+250+10,340,250) end - draw.SimpleText("связь","Metrostroi_Arial20",15+340-5,300+250, Color(50,200,50),TEXT_ALIGN_RIGHT,TEXT_ALIGN_CENTER) - else - surface.SetDrawColor(0,0,0,255) - surface.DrawRect(15,50+250+10,340,250) - draw.SimpleText("Подключение к камере...","Metrostroi_Arial30",15+340/2,310+250/2, Color(200,200,200),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - draw.SimpleText("нет связи","Metrostroi_Arial20",15+340-5,300+250, Color(200,50,50),TEXT_ALIGN_RIGHT,TEXT_ALIGN_CENTER) - end - draw.SimpleText("[3]"..Format(types[camtype][3],WagNum),"Metrostroi_Arial20",15+5,310+10, Color(200,150,50),TEXT_ALIGN_LEFT,TEXT_ALIGN_CENTER) - draw.SimpleText(Format("Вагон №%d",Train:GetNW2Int("SarmatCam3EN")),"Metrostroi_Arial20",15+5,310+30, Color(200,150,50),TEXT_ALIGN_LEFT,TEXT_ALIGN_CENTER) - Metrostroi.DrawRectOutline(15,50+250+10,340,250,Color(40,40,40),2) - end - if CamCount > 3 then - local invert = inverts[camtype][4] - if Cam4 then - surface.SetDrawColor(255,255,255,255) - if invert then render.DrawTextureToScreenRect(self.Cam4,340+15+10+340,50+250+10,-340,250) else render.DrawTextureToScreenRect(self.Cam4,340+15+10,50+250+10,340,250) end - draw.SimpleText("связь","Metrostroi_Arial20",365+340-5,300+250, Color(50,200,50),TEXT_ALIGN_RIGHT,TEXT_ALIGN_CENTER) - else - surface.SetDrawColor(0,0,0,255) - surface.DrawRect(340+15+10,50+250+10,340,250) - draw.SimpleText("Подключение к камере...","Metrostroi_Arial30",365+340/2,310+250/2, Color(200,200,200),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - draw.SimpleText("нет связи","Metrostroi_Arial20",365+340-5,300+250, Color(200,50,50),TEXT_ALIGN_RIGHT,TEXT_ALIGN_CENTER) - end - draw.SimpleText("[4]"..Format(types[camtype][4],WagNum),"Metrostroi_Arial20",365+5,310+10, Color(200,150,50),TEXT_ALIGN_LEFT,TEXT_ALIGN_CENTER) - draw.SimpleText(Format("Вагон №%d",Train:GetNW2Int("SarmatCam4EN")),"Metrostroi_Arial20",365+5,310+30, Color(200,150,50),TEXT_ALIGN_LEFT,TEXT_ALIGN_CENTER) - Metrostroi.DrawRectOutline(340+15+10,50+250+10,340,250,Color(40,40,40),2) - end - surface.SetDrawColor(127,127,127) - surface.SetTexture(button) - drawButton(110,590,200,40,"Esc") - --drawButton(320,590,200,40,"<-") - --drawButton(530,590,200,40,"->") - end - --surface.SetTexture( self.Cam1 ) - --surface.SetDrawColor( 255, 0, 0, 255 ) - --[[ - - - - --] - --[[ - render.DrawTextureToScreenRect(self.Cam1,15,50,340,510) - render.DrawTextureToScreenRect(self.Cam2,340+15+10,50,340,510)--]] - --[[ - for i=1,#Metrostroi.WorkingStations[line] do - local st = Metrostroi.WorkingStations[line][i] - draw.SimpleText(Metrostroi.AnnouncerTranslate[st],"Metrostroi_Arial25",760,80+i*30, Color(200,200,200),TEXT_ALIGN_LEFT,TEXT_ALIGN_CENTER) - end]] - --draw.SimpleText("Блок неактивен","Metrostroi_Arial25",870,100, Color(200,200,200),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) + -- БМТС-07 ЦИКВ.402261.031 + if self.Train:ShouldDrawPanel("BMTS") then + local BMTSText = self.Train:GetNW2String("BMTS:Text","") + local BMTSState = self.Train:GetNW2Int("BMTS:State",0) + if self.BMTS.State ~= BMTSState then + self.BMTS.State = BMTSState + self.BMTS.Update = true end - if state ~= 0 then - surface.SetDrawColor(0,0,20,100) - surface.DrawRect(0,0,1024,640) + if self.BMTS.State > 0 and self.BMTS.Text ~= BMTSText then + self.BMTS.Text = BMTSText + self.BMTS.Update = true + end + + if self.BMTS.Update then + render.PushRenderTarget(self.Train.BMTSScr,0,0,512,128) + render.Clear(0, 0, 0, 0) + cam.Start2D() + self:BMTS07(self.Train) + render.OverrideBlend(true,BLEND_ZERO,BLEND_ONE,BLENDFUNC_ADD,BLEND_ZERO,BLEND_ZERO,BLENDFUNC_MIN) + surface.SetDrawColor(255,255,255,200) + surface.SetTexture(BMTSPixels) + surface.DrawTexturedRectRotated(256,64,512,128,0) + render.OverrideBlend(false) + cam.End2D() + render.PopRenderTarget() + self.BMTS.Update = false end end end + +local sarmatLogo = surface.GetTextureID("models/metrostroi_train/81-722/screens/sarmat_upo/sarmat_logo") +local grubMenu = surface.GetTextureID("models/metrostroi_train/81-722/screens/sarmat_upo/grub") +function TRAIN_SYSTEM:BMCIK01(Train,state) + if state == 0 then return end + if state == -4 then + local grubTimeout = Train:GetNW2Int("BMCIK:GRUBTimeout",0) + surface.SetTexture(grubMenu) + surface.SetDrawColor(255,255,255) + + local mat = Matrix() + mat:SetScale(Vector(2,1.667)) + cam.PushModelMatrix(mat) + surface.DrawTexturedRect(0,0,1024,512) + surface.DrawTexturedRectUV(482,398,8,12,0.625+grubTimeout*0.0078125,0,0.6328125+grubTimeout*0.0078125,0.0234375) + cam.PopModelMatrix() + elseif state == -3 then + if (CurTime()%0.5 > 0.25) then + surface.SetTextColor(255,255,255) + surface.SetFont(font28) + drawText("_",2,2) + end + elseif state == -2 then + draw.SimpleText("_",font28,2,16, Color(255,255,255),TEXT_ALIGN_LEFT,TEXT_ALIGN_CENTER) + surface.SetTexture(sarmatLogo) + surface.SetDrawColor(250,190,0) + surface.DrawTexturedRectRotated(955,685,640,320,0) + elseif state == 1 then + self:BMCIK01State1(Train) + + surface.SetAlphaMultiplier(1-self.Train:GetNW2Float("BMCIK:Brightness",1)^1.2) + surface.SetDrawColor(Color(8,8,8)) + surface.DrawRect(0,0,1280,800,0) + surface.SetAlphaMultiplier(1) + end +end + +function TRAIN_SYSTEM:BMCIK01State1(Train) + self.WagNum = Train:GetNW2Int("BMCIK:WagNum",0) + + self:BMCIK01GUICameras(Train) + self:BMCIK01GUIAnnouncer(Train) + + surface.SetFont(font28) + surface.SetTextColor(255,255,255) + drawText(os.date("!%d.%m.%y %H:%M:%S",Metrostroi.GetSyncTime()),681,742) + drawText("Ver. 6",681,768) +end + +local function drawButton(x,y,w,h,text,touched) + draw.RoundedBox(8,x,y,w,h,Color(255,255,255)) + draw.RoundedBox(6,x+2,y+2,w-4,h-4,touched and Color(83,83,83) or Color(35,35,35)) + + drawText(text,x+w/2,y+h/2,TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) +end + +local BMCIKPos = Vector(472,37.4,-9) +local camFrame = surface.GetTextureID("models/metrostroi_train/81-722/screens/sarmat_upo/cam_frame") +function TRAIN_SYSTEM:BMCIK01GUICameras(Train) + local wagNum = self.WagNum + local camPage = Train:GetNW2Int("BMCIK:CamPage",0) + local touchId = Train:GetNW2Int("BMCIK:IDTouched",0) + + surface.SetFont(font28) + surface.SetTextColor(255,255,255) + for i=1,self.Buttons.Count do + local btn = self.Buttons[i] + if btn.show(camPage) then + drawButton(btn.x,btn.y,btn.w,btn.h,Format(btn.name,wagNum),touchId == btn.id) + end + end + if camPage == 0 then + drawText("Система видеонаблюдения",457,32,TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) + + for i=1,self.Buttons.Count do + local btn = self.Buttons[i] + drawButton(btn.x,btn.y,btn.w,btn.h,Format(btn.name,wagNum),touchId == btn.id) + end + + drawText("Наружные камеры",457,129,TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) + drawText("1",74,185) + drawText(wagNum,74,213) + drawText("Вагон 1",311,163,TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) + drawText("Все вагоны",457,163,TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) + drawText("Вагон "..wagNum,603,163,TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) + drawText("1",825,185) + drawText(wagNum,825,213) + + drawText("Камеры в салонах",457,303,TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) + for i=1,wagNum do + if wagNum == 8 then + drawButton(350+(i-wagNum/2)*110,323,104,60,"Вагон "..i,touchId == 10+i) + elseif wagNum == 7 then + drawButton(334+(i-wagNum/2)*126,323,120,60,"Вагон "..i,touchId == 10+i) + else + drawButton(313+(i-wagNum/2)*147,323,141,60,"Вагон "..i,touchId == 10+i) + end + end + + drawText("Камеры на постах машиниста",457,443,TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) + drawText("Путевые камеры",457,583,TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) + else + -- Номер вагона, тип вагона, бортовой номер + local camWagIndex = Train:GetNW2Int("BMCIK:CamWagIndex",0) + local camWagType = Train:GetNW2Int("BMCIK:CamType",0) + local camWagNum = Train:GetNW2Int("BMCIK:CamWagNumber",0) + local camCurrConf = self.CamConfig[camWagType][camPage] or self.CamConfig[0][1] + + surface.SetFont("Metrostroi_Dejavu26") + local headerCurr = Format("Вагон %d [%d] - %s - страница %d/%d",camWagIndex,camWagNum,camCurrConf.PageName,camPage,self.CamConfig[camWagType].Count) + local headerCurrW = surface.GetTextSize(headerCurr) + + surface.SetDrawColor(255,255,255) + surface.SetTexture(camFrame) + surface.DrawTexturedRectRotated(530,542,1024,1024,0) + + surface.SetDrawColor(0,0,0) + surface.DrawRect(457 - ((headerCurrW+10)/2-0.5),30,headerCurrW+10,1) + drawText(headerCurr,457 - headerCurrW/2,20) + + local CamNW2 = Train:GetNW2Int("BMCIK:Cam",0) + local Cam1 = getBitValue(CamNW2,0,1) > 0 + local Cam2 = camCurrConf.Count > 1 and getBitValue(CamNW2,1,1) > 0 + local Cam3 = camCurrConf.Count > 2 and getBitValue(CamNW2,2,1) > 0 + local Cam4 = camCurrConf.Count > 3 and getBitValue(CamNW2,3,1) > 0 + + local camTbl + if Cam1 then + camTbl = camCurrConf[1] + Metrostroi.RenderCamOnRT(Train,BMCIKPos,"Cam1",0.1+0.15*math.random(),self.Cams[1][1],Train:GetNW2Entity("BMCIK:CamE1"),camTbl[2],camTbl[3],512,512,not camTbl.wide and 1.4,not camTbl.wide and 74,not camTbl.wide and 74) + self.Cams[1][2] = Metrostroi.CamQueue[1] and (Metrostroi.CamQueue[1][3]:EndsWith("1") and math.floor(1/Metrostroi.CamQueue[1][4])) or self.Cams[1][2] + end + if Cam2 then + camTbl = camCurrConf[2] + Metrostroi.RenderCamOnRT(Train,BMCIKPos,"Cam2",0.1+0.15*math.random(),self.Cams[2][1],Train:GetNW2Entity("BMCIK:CamE2"),camTbl[2],camTbl[3],512,512,not camTbl.wide and 1.4,not camTbl.wide and 74,not camTbl.wide and 74) + self.Cams[2][2] = Metrostroi.CamQueue[1] and (Metrostroi.CamQueue[1][3]:EndsWith("2") and math.floor(1/Metrostroi.CamQueue[1][4])) or self.Cams[2][2] + end + if Cam3 then + camTbl = camCurrConf[3] + Metrostroi.RenderCamOnRT(Train,BMCIKPos,"Cam3",0.1+0.15*math.random(),self.Cams[3][1],Train:GetNW2Entity("BMCIK:CamE3"),camTbl[2],camTbl[3],512,512,not camTbl.wide and 1.4,not camTbl.wide and 74,not camTbl.wide and 74) + self.Cams[3][2] = Metrostroi.CamQueue[1] and (Metrostroi.CamQueue[1][3]:EndsWith("3") and math.floor(1/Metrostroi.CamQueue[1][4])) or self.Cams[3][2] + end + if Cam4 then + camTbl = camCurrConf[4] + Metrostroi.RenderCamOnRT(Train,BMCIKPos,"Cam4",0.1+0.15*math.random(),self.Cams[4][1],Train:GetNW2Entity("BMCIK:CamE4"),camTbl[2],camTbl[3],512,512,not camTbl.wide and 1.4,not camTbl.wide and 74,not camTbl.wide and 74) + self.Cams[4][2] = Metrostroi.CamQueue[1] and (Metrostroi.CamQueue[1][3]:EndsWith("4") and math.floor(1/Metrostroi.CamQueue[1][4])) or self.Cams[4][2] + end + + local camFullScreen = getBitValue(CamNW2,4,3) + surface.SetFont(font20) + if camFullScreen > 0 then + local tCam = getBitValue(CamNW2,camFullScreen-1,1) > 0 + if tCam then + render.DrawTextureToScreenRect(self.Cams[camFullScreen][1],scx*24,scy*58,scx*866,scy*662) + surface.SetTextColor(200,0,0) + drawText("fps = "..(self.Cams[camFullScreen][2]),26,78) + + surface.SetTextColor(0,200,0) + drawText("link",888,698,TEXT_ALIGN_RIGHT) + else + surface.SetTextColor(200,0,0) + drawText("no link",888,698,TEXT_ALIGN_RIGHT) + end + Metrostroi.DrawRectOutline(24,58,867,663,Color(176,176,176)) + surface.SetTextColor(250,200,0) + drawText(camCurrConf[camFullScreen][1],26,58) + elseif camCurrConf.Count == 4 then + -- Top left + if Cam1 then + render.DrawTextureToScreenRect(self.Cams[1][1],scx*24,scy*58,scx*430,scy*328) + surface.SetTextColor(200,0,0) + drawText("fps = "..(self.Cams[1][2]),26,78) + + surface.SetTextColor(0,200,0) + drawText("link",451,364,TEXT_ALIGN_RIGHT) + else + surface.SetTextColor(200,0,0) + drawText("no link",451,364,TEXT_ALIGN_RIGHT) + end + + -- Top right + if Cam2 then + render.DrawTextureToScreenRect(self.Cams[2][1],scx*460,scy*58,scx*430,scy*328) + surface.SetTextColor(200,0,0) + drawText("fps = "..(self.Cams[2][2]),462,78) + + surface.SetTextColor(0,200,0) + drawText("link",888,364,TEXT_ALIGN_RIGHT) + else + surface.SetTextColor(200,0,0) + drawText("no link",888,364,TEXT_ALIGN_RIGHT) + end + + -- Bottom left + if Cam3 then + render.DrawTextureToScreenRect(self.Cams[3][1],scx*24,scy*392,scx*430,scy*328) + surface.SetTextColor(200,0,0) + drawText("fps = "..(self.Cams[3][2]),26,414) + + surface.SetTextColor(0,200,0) + drawText("link",451,698,TEXT_ALIGN_RIGHT) + else + surface.SetTextColor(200,0,0) + drawText("no link",451,698,TEXT_ALIGN_RIGHT) + end + + -- Bottom right + if Cam4 then + render.DrawTextureToScreenRect(self.Cams[4][1],scx*460,scy*392,scx*430,scy*328) + surface.SetTextColor(200,0,0) + drawText("fps = "..(self.Cams[4][2]),462,414) + + surface.SetTextColor(0,200,0) + drawText("link",888,698,TEXT_ALIGN_RIGHT) + else + surface.SetTextColor(200,0,0) + drawText("no link",888,698,TEXT_ALIGN_RIGHT) + end + + + Metrostroi.DrawRectOutline(24,58,431,329,Color(176,176,176)) + Metrostroi.DrawRectOutline(460,58,431,329,Color(176,176,176)) + Metrostroi.DrawRectOutline(24,392,431,329,Color(176,176,176)) + Metrostroi.DrawRectOutline(460,392,431,329,Color(176,176,176)) + + surface.SetTextColor(250,200,0) + drawText(camCurrConf[1][1],26,58) + drawText(camCurrConf[2][1],462,58) + drawText(camCurrConf[3][1],26,394) + drawText(camCurrConf[4][1],462,394) + elseif camCurrConf.Count == 2 then + -- Left + if Cam1 then + render.DrawTextureToScreenRect(self.Cams[1][1],scx*24,scy*58,scx*430,scy*662) + surface.SetTextColor(200,0,0) + drawText("fps = "..(self.Cams[1][2]),26,78) + + surface.SetTextColor(0,200,0) + drawText("link",451,698,TEXT_ALIGN_RIGHT) + else + surface.SetTextColor(200,0,0) + drawText("no link",451,698,TEXT_ALIGN_RIGHT) + end + + -- Right + if Cam2 then + render.DrawTextureToScreenRect(self.Cams[2][1],scx*460,scy*58,scx*430,scy*662) + surface.SetTextColor(200,0,0) + drawText("fps = "..(self.Cams[2][2]),462,78) + + surface.SetTextColor(0,200,0) + drawText("link",888,698,TEXT_ALIGN_RIGHT) + else + surface.SetTextColor(200,0,0) + drawText("no link",888,698,TEXT_ALIGN_RIGHT) + end + + + Metrostroi.DrawRectOutline(24,58,431,663,Color(176,176,176)) + Metrostroi.DrawRectOutline(460,58,431,663,Color(176,176,176)) + + surface.SetTextColor(250,200,0) + drawText(camCurrConf[1][1],26,58) + drawText(camCurrConf[2][1],462,58) + else + if Cam1 then + render.DrawTextureToScreenRect(self.Cams[1][1],scx*24,scy*58,scx*866,scy*662) + surface.SetTextColor(200,0,0) + drawText("fps = "..(self.Cams[1][2]),26,78) + + surface.SetTextColor(0,200,0) + drawText("link",888,698,TEXT_ALIGN_RIGHT) + else + surface.SetTextColor(200,0,0) + drawText("no link",888,698,TEXT_ALIGN_RIGHT) + end + Metrostroi.DrawRectOutline(24,58,867,663,Color(176,176,176)) + surface.SetTextColor(250,200,0) + drawText(camCurrConf[1][1],26,58) + end + end +end + +local listCursor = surface.GetTextureID("models/metrostroi_train/81-722/screens/sarmat_upo/list_cursor") +function TRAIN_SYSTEM:DrawListLine(text,pos,selected) + pos = pos - self.List.Offset + if selected then + surface.SetTexture(listCursor) + surface.SetDrawColor(176,176,176) + surface.DrawTexturedRectRotated(1174,132+(pos-1)*24,512,32,0) + + surface.SetTextColor(0,0,0) + else + surface.SetTextColor(255,255,255) + end + + drawText(tostring(text),selected and 924 or 920,94+pos*24) +end + +local annFrame = surface.GetTextureID("models/metrostroi_train/81-722/screens/sarmat_upo/ann_frame") +local lineFrame = surface.GetTextureID("models/metrostroi_train/81-722/screens/sarmat_upo/line_frame") +local trainTrainMsg = surface.GetTextureID("models/metrostroi_train/81-722/screens/sarmat_upo/traintrain_msg") +function TRAIN_SYSTEM:BMCIK01GUIAnnouncer(Train) + local listSelected = Train:GetNW2Int("BMCIK:ListSelect"); self.List.Selected = listSelected; + local listOffset = Train:GetNW2Int("BMCIK:ListOffset"); self.List.Offset = listOffset; + + local annNW2 = Train:GetNW2Int("BMCIK:Announcer") + local annState = getBitValue(annNW2,0,6) + local annLine = getBitValue(annNW2,10,8) + local annLimit = getBitValue(annNW2,18,12); annLimit = annLimit > 0 and annLimit + local annPath = getBitValue(annNW2,30,1) > 0 + local annPathSel = getBitValue(annNW2,31,1) > 0 + + local annTbl = Metrostroi.SarmatUPOSetup[Train:GetNW2Int("Announcer")] + local lTbl = annTbl and annTbl[annLine] + local lTblCount = lTbl and #lTbl or 0 + + surface.SetFont(font28) + surface.SetTextColor(255,255,255) + drawText("линия",1054,11) + drawText(lTbl and "ПУТЬ "..(annPathSel and 2 or 1) or "---",1213,25,TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) + + surface.SetTexture(lineFrame) + if Train:GetNW2Bool("BMCIK:LineEnabled") then + surface.SetDrawColor(0,255,0) + surface.SetTextColor(0,255,0) + else + surface.SetDrawColor(59,59,59) + surface.SetTextColor(59,59,59) + end + surface.DrawTexturedRectRotated(1096,25,128,32,0) + drawText("линия",1053,10) + + -- Header + surface.SetTextColor(255,255,255) + if annState < 2 then + local lNameHeader = "---" + if lTbl then + if lTbl.Name then + lNameHeader = "Линия: "..lTbl.Name + else + local fSt = annPath and 1 or lTblCount + local lSt = annLimit or (annPath and 1 or lTblCount) + lNameHeader = Format("Линия: %s-%s",lTbl[fSt][2],lTbl[lSt][2]) -- "Линия: " = 92px + end + if surface.GetTextSize(lNameHeader) > 355 then + lNameHeader = lNameHeader:gsub("-","-\n",1) + end + end + self.HeaderNames[0] = lNameHeader + self.HeaderNames[1] = self.HeaderNames[0] + end + local textHeader = string.Explode("\n",self.HeaderNames[annState]) + for i=1,#textHeader do + drawText(textHeader[i],1091,78-(#textHeader-1)*14+(i-1)*28,TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) + end + + -- White frame + if annState > 0 and annState ~= 21 then + surface.SetDrawColor(255,255,255) + surface.SetTexture(annFrame) + surface.DrawTexturedRectRotated(1169,623,512,1024,0) + end + + -- Lists + render.SetScissorRect(918,116,1264,637,true) + surface.SetFont(font21) + if annState == 0 then + surface.SetFont(font28) + drawText("Блок неактивен",992,112) + elseif annState == 1 then + if annPath then + for i=lTblCount,1,-1 do + if annLimit and i < annLimit then break end + local iPos=(lTblCount-i+1)*2 + + self:DrawListLine(lTbl[i][2],iPos-1,listSelected==(iPos-1)) + self:DrawListLine(lTbl[i][2].." отп",iPos,listSelected==iPos) + end + else + for i=1,lTblCount do + if annLimit and i > annLimit then break end + local iPos=i*2 + + self:DrawListLine(lTbl[i][2],i*2-1,listSelected==(i*2-1)) + self:DrawListLine(lTbl[i][2].." отп",i*2,listSelected==(i*2)) + end + end + elseif annState > 10 and annState < 20 then + if annState == 11 then -- Предупредительные сообщения + self:DrawListLine("Нет сообщений",1,true) + elseif annState == 12 then -- Ограничения маршрута + local iLast = 1 + if lTbl.Loop then + for i=1,lTblCount do + if lTbl[i].arrlast then + self:DrawListLine((annLimit == i and "☑ " or "☐ ")..lTbl[i][2],iLast,listSelected==iLast) + iLast = iLast + 1 + end + end + else + for i=2,lTblCount-1 do + if lTbl[i].arrlast then + self:DrawListLine((annLimit == i and "☑ " or "☐ ")..lTbl[i][2],iLast,listSelected==iLast) + iLast = iLast + 1 + end + end + end + elseif annState == 13 then -- Дополнительные сообщения + self:DrawListLine("Нет сообщений",1,true) + elseif annState == 14 then -- Экстренные сообщение + self:DrawListLine("Нет сообщений",1,true) + elseif annState == 15 then -- Выбор линии + for i=1,#annTbl do + local lName = annTbl[i].Name or Format("%s-%s",annTbl[i][1][2],annTbl[i][#annTbl[i]][2]) + self:DrawListLine(lName,i,listSelected==i) + end + end + elseif annState == 2 then -- Меню настройки блока СБУЦИК + for i=1,#self.SettingsList do + self:DrawListLine(self.SettingsList[i][1],i,listSelected==i) + end + elseif annState > 20 then + if annState == 21 then -- Ввод номера маршрута + surface.SetFont(font28) + drawText("Ввод номера маршрута",945,112) + elseif annState == 22 then -- Режимы работы информатора + local mode = Train:GetNW2Int("BMCIK:AnnMode",0) + for i=1,#self.AnnModeList do + self:DrawListLine((mode == i and "☑ " or "☐ ")..self.AnnModeList[i],i,listSelected==i) + end + elseif annState == 23 then -- Режимы работы СОСТАВ-СОСТАВ + local mode = Train:GetNW2Bool("BMCIK:TrainTrain") + self:DrawListLine((mode and "☑ " or "☐ ").."Режим 'Состав-Состав'",1,true) + if mode then + render.SetScissorRect(0,0,0,0,false) + surface.SetDrawColor(255,255,255) + surface.DrawRect(900,400,378,250) + surface.SetTexture(trainTrainMsg) + surface.DrawTexturedRectRotated(1156,528,512,256,0) + end + elseif annState == 24 then -- Настройка громкости + local volumes = Train:GetNW2Int("BMCIK:VolumesPage") + local volumeList = self.AnnVolumeList + for i=1,#volumeList do + self:DrawListLine(volumeList[i][1],i,listSelected==i) + drawText(getBitValue(volumes,(i-1)*4,4)*10,1230,118+(i-1)*24,TEXT_ALIGN_CENTER) + end + elseif annState == 25 then -- Информация + local info = self.InfoList + local infoNW2 = Train:GetNW2Int("BMCIK:AddInfo",0) + for i=1,#info do + local v = info[i][2] and Train:GetNW2Int(info[i][2]) or 0 + self:DrawListLine(info[i][1]..v,i,listSelected==i) + end + elseif annState == 26 then -- Диагностика + for i=1,#self.DiagList do + self:DrawListLine(self.DiagList[i],i,listSelected==i) + end + elseif annState == 27 then -- Язык + -- TODO: Add translations support + local mode = 1 + for i=1,#self.LangList do + self:DrawListLine((mode==i and "☑ " or "☐ ")..self.LangList[i],i,listSelected==i) + end + elseif annState == 28 then -- Отображение времени на БИТ + local mode = Train:GetNW2Bool("BMCIK:BITTime") and 2 or 1 + for i=1,#self.BITClockList do + self:DrawListLine((mode==i and "☑ " or "☐ ")..self.BITClockList[i],i,listSelected==i) + end + end + end + render.SetScissorRect(0,0,0,0,false) + + surface.SetTextColor(255,255,255) + surface.SetFont("Metrostroi_Dejavu22") + drawText("Состав:",924,647) + + surface.SetFont(font28) + local wagNum = self.WagNum + for i=0,wagNum-1 do + drawButton(1091+(i-wagNum/2)*41,673,40,48,i+1) + end + + local cikState = getBitValue(annNW2,6,4) + drawText(self.CIKStatesNames[cikState],913,756) +end + +local function stringUpperCyrillic(str) + if #str == 0 then return "" end + local strtbl = {utf8.codepoint(str,1,-1)} + local strUp = "" + for i=1,#strtbl do + local chartbl = strtbl[i] + if chartbl > 0x042F and chartbl < 0x0450 then chartbl = chartbl - 0x20 -- [а,я] --> [A,Я] + elseif chartbl == 0x0456 then chartbl = 0x0406 -- і -> І + elseif chartbl == 0x0451 then chartbl = 0x0401 -- ё -> Ё + elseif chartbl == 0x0457 then chartbl = 0x0407 -- ї -> Ї + elseif chartbl == 0x0454 then chartbl = 0x0404 -- є -> Є + elseif chartbl == 0x045E then chartbl = 0x040E -- ў -> Ў + elseif chartbl == 0x0491 then chartbl = 0x0490 -- ґ -> Ґ + end + + strUp = strUp..(utf8.char(chartbl)) + end + return string.upper(strUp) +end + +function TRAIN_SYSTEM:BMTS07(Train) + local state = self.BMTS.State + if state == 0 then return end + if state == 1 then + surface.SetFont("Metrostroi_BMTS4") + surface.SetTextColor(255,120,0) + local lastStation = stringUpperCyrillic(self.BMTS.Text) + local lsW,lsY = surface.GetTextSize(lastStation),-5 + if lsW >= 230 then + surface.SetFont("Metrostroi_BMTS1") + lsW = surface.GetTextSize(lastStation) + lsY = 3 + elseif lsW >= 168 then + surface.SetFont("Metrostroi_BMTS2") + lsW = surface.GetTextSize(lastStation) + lsY = 2 + elseif lsW >= 126 then + surface.SetFont("Metrostroi_BMTS3") + lsW = surface.GetTextSize(lastStation) + lsY = -1 + end + local mat = Matrix() + mat:Scale(Vector(4,4)) + cam.PushModelMatrix(mat) + surface.SetTextPos(64-lsW/2, lsY) + surface.DrawText(lastStation) + cam.PopModelMatrix() + elseif state == -1 then + surface.SetDrawColor(255,120,0) + surface.DrawRect(0,0,512,80) + end +end \ No newline at end of file diff --git a/lua/metrostroi/systems/sys_81_722_tickers.lua b/lua/metrostroi/systems/sys_81_722_tickers.lua index 96eda8e..018736c 100644 --- a/lua/metrostroi/systems/sys_81_722_tickers.lua +++ b/lua/metrostroi/systems/sys_81_722_tickers.lua @@ -1,13 +1,27 @@ -------------------------------------------------------------------------------- --- 81-722 tickers +-- 81-722 BIT-20 system -------------------------------------------------------------------------------- -- Copyright (C) 2013-2018 Metrostroi Team & FoxWorks Aerospace s.r.o. -- Contains proprietary code. See license.txt for additional information. -------------------------------------------------------------------------------- -Metrostroi.DefineSystem("81_722_Tickers") +Metrostroi.DefineSystem("81_722_BIT") TRAIN_SYSTEM.DontAccelerateSimulation = true function TRAIN_SYSTEM:Initialize() + self.State = 0 + self.Data = { + Left = "< ", + Right = " >", + TextStr = "---", + Text = {"---"}, + Loop = 1 + } + self.TextTimer = 0 + -- self.DopText = "---" + self.ShowTime = false + if not TURBOSTROI then + self.IP = self.Train:GetWagonNumber()%255 + end end function TRAIN_SYSTEM:Outputs() @@ -18,41 +32,118 @@ function TRAIN_SYSTEM:Inputs() return {} end if TURBOSTROI then return end -function TRAIN_SYSTEM:TriggerInput(name,value) + +local function setBitValue(targetVar, value, offset, bitCount) + value = bit.band(value,bit.lshift(1,bitCount)-1) + return bit.bor(targetVar,bit.lshift(value,offset)) end + +local function getBitValue(value, offset, bitCount) + local mask = bit.lshift(bit.lshift(1,bitCount)-1,offset) + return bit.rshift(bit.band(value,mask),offset) +end + +TRAIN_SYSTEM.CAN_ACTIVATE = 0x01 +TRAIN_SYSTEM.CAN_CIKSTATE = 0x02 + +TRAIN_SYSTEM.CAN_BMTS_TEXT = 0x10 + +TRAIN_SYSTEM.CAN_CURR = 0x21 +TRAIN_SYSTEM.CAN_NEXT = 0x22 +TRAIN_SYSTEM.CAN_PATH = 0x23 +TRAIN_SYSTEM.CAN_CLOSERING = 0x24 +TRAIN_SYSTEM.CAN_VOLUMES = 0x25 +TRAIN_SYSTEM.CAN_SPEED = 0x26 + +TRAIN_SYSTEM.CAN_BITTEXT = 0x30 +TRAIN_SYSTEM.CAN_BITDOPMSG = 0x31 +TRAIN_SYSTEM.CAN_BITTIME = 0x32 + if SERVER then function TRAIN_SYSTEM:CANReceive(source,sourceid,target,targetid,textdata,numdata) - if textdata=="Arrived" then - if self.Arrived ~= numdata then - self.TimerRand = math.Rand(-10,10) - self.Arrived = numdata - end - else - self[textdata]=numdata + if self.State < 1 then return end + if textdata == self.CAN_ACTIVATE then + self.State = 1 + self.CurrentShowIndex = 1 + end + if textdata == self.CAN_BITTEXT then + self.TextTimer = CurTime()-1 + self.Data.Text = numdata.Text + self.Data.Left = numdata.Left or "< " + self.Data.Right = numdata.Right or " >" + self.Data.Loop = numdata.Loop or 1 + self.CurrentShowIndex = 0 + end + if textdata == self.CAN_BITTIME then + self.ShowTime = numdata end end function TRAIN_SYSTEM:Think(dT) local Train = self.Train - local Power = Train.Panel.PassSchemePowerL>0 and Train.Panel.PassSchemePowerR>0 + local Power = Train.Panel.PassSchemePowerL>0 or Train.Panel.PassSchemePowerR>0 if Power then - if not self.TimerRand then self.TimerRand = math.Rand(-10,10) end - Train:SetNW2Int("TickersRandom",self.TimerRand*10) - Train:SetNW2String("TickersPrev",self.Prev or "") - Train:SetNW2String("TickersPrevEn",self.PrevEn or "") - Train:SetNW2String("TickersNext",self.Next or "") - Train:SetNW2Bool("TickersNextRight",self.NextRight) - Train:SetNW2String("TickersNextEn",self.NextEn or "") - Train:SetNW2String("TickersCurr",self.Curr or "") - Train:SetNW2String("TickersCurrEn",self.CurrEn or "") - Train:SetNW2Bool("TickersCurrRight",self.CurrRight) - Train:SetNW2Bool("TickersArrived",self.Arrived or "") - Train:SetNW2Bool("TickersLast",self.Last) - Train:SetNW2Bool("TickersClosing",self.Closing) - Train:SetNW2String("TickersSpecial",self.Special or "") - elseif self.TimerRand then - self.TimerRand = nil + if self.State > 0 then + if self.State == 1 then + if CurTime() > self.TextTimer then + self.TextTimer = CurTime()+math.Rand(2,2.2) + self.CurrentShowIndex = self.CurrentShowIndex + 1 + if self.CurrentShowIndex > #self.Data.Text then + self.CurrentShowIndex = self.Data.Loop + end + + Train:SetNW2String("BIT:Text",self.Data.Text[self.CurrentShowIndex]) + Train:SetNW2String("BIT:TextLeft",self.Data.Left) + Train:SetNW2String("BIT:TextRight",self.Data.Right) + end + + elseif self.State == 2 then + if CurTime() > self.TextTimer then + self.TextTimer = CurTime()+2.1 + self.ShowIP = not self.ShowIP + end + + local ip = 0 + ip = setBitValue(ip,self.ShowIP and 1 or 0,0,1) + ip = setBitValue(ip,self.IP,1,8) + Train:SetNW2Int("BIT:IP",ip) + end + Train:SetNW2Bool("BIT:Time",self.ShowTime) + elseif self.State < 0 then + if self.LoadingTimer and CurTime() > self.LoadingTimer then + if self.State == -3 then + self.State = -2 + self.LoadingTimer = CurTime()+math.Rand(3,4) + elseif self.State == -2 then + self.State = -1 + self.LoadingTimer = CurTime()+math.Rand(9,11) + elseif self.State == -1 then + self.State = 2 + self.TextTimer = CurTime()+2 + self.ShowIP = true + self.LoadingTimer = nil + end + end + else + self.State = -3 + self.LoadingTimer = CurTime()+math.Rand(1,3) + end + else + if self.State ~= 0 then + self.State = 0 + self.Data = { + Left = "< ", + Right = " >", + TextStr = "---", + Text = {"---"}, + Loop = 1 + } + self.CurrentShowIndex = 1 + self.TextTimer = 0 + -- self.DopText = "---" + end end - Train:SetNW2Bool("TickersPower",Power) + + Train:SetNW2Int("BIT:State",self.State) end else local function createFont(name,font,size,weight) @@ -73,104 +164,119 @@ else extended = true, }) end - --createFont("BUKPSpeed","Eurostar Metrostroi",80) - --createFont("Arial15","Arial",15,800) - --createFont("Arial20","Arial",20,800) - --createFont("Arial22","Arial",22,400) - --createFont("Arial40","Arial",30,400) - createFont("TNR30","Times new roman",30,400) - createFont("TNR60","Times new roman",60,400) + + local function drawText(text,x,y,xalign,yalign) + if (xalign or yalign) then + local w,h = surface.GetTextSize( text ) + if (xalign == TEXT_ALIGN_CENTER) then + x = x - w / 2 + elseif (xalign == TEXT_ALIGN_RIGHT) then + x = x - w + end + + if (yalign == TEXT_ALIGN_CENTER) then + y = y - h / 2 + elseif (yalign == TEXT_ALIGN_BOTTOM) then + y = y - h + end + end + surface.SetTextPos(x,y) + surface.DrawText(text) + end + + createFont("BIT1","Ubuntu Condensed",54) + createFont("BIT2","Liberation Serif",103) + createFont("BIT3","Liberation Serif",30) + + local tDay = {"пн","вт","ср","чт","пт","сб","вс"} + local tMonth = {"янв","фев","мар","апр","мая","июня","июля","авг","сен","окт","ноя","дек"} function TRAIN_SYSTEM:ClientInitialize() - self.TimerCorrection = 0 end function TRAIN_SYSTEM:ClientThink() - if not self.Train:ShouldDrawPanel("Tickers") then return end - local train = self.Train - render.PushRenderTarget(self.Train.Tickers,0,0,1024, 128) + if not self.Train:ShouldDrawPanel("BIT1") then return end + render.PushRenderTarget(self.Train.BITScr,0,0,1024, 256) render.Clear(0, 0, 0, 0) cam.Start2D() - surface.SetDrawColor(0,0,0) - surface.DrawRect(0,0,600,128) - self:Tickers(self.Train) + self:BIT(self.Train) cam.End2D() render.PopRenderTarget() end - --SarmatCam2T - function TRAIN_SYSTEM:Tickers(Train) - surface.SetDrawColor(0,0,0,80) - surface.DrawRect(0,0,600,128) - local state = Train:GetNW2Bool("TickersPower",false) - if state then - local arr = Train:GetNW2Bool("TickersArrived") - local last = Train:GetNW2Bool("TickersLast") - local closing = Train:GetNW2Bool("TickersClosing") - local nxt,nxtEn,nxtR = Train:GetNW2String("TickersNext",""),Train:GetNW2String("TickersNextEn",""),Train:GetNW2Bool("TickersNextRight") - local prev = Train:GetNW2String("TickersPrev",""),Train:GetNW2String("TickersPrevEn","") - local curr,currEn,currR = Train:GetNW2String("TickersCurr",""),Train:GetNW2String("TickersCurrEn",""),Train:GetNW2Bool("TickersCurrRight") - local special = Train:GetNW2String("TickersSpecial","") - local str = "" - if (arr or closing) and last then - str = Format("Поезд прибыл\nна конечную станцию\n%s",curr or "...") - if currR then str = str..",\nвыход на правую сторону" end - if currEn~="" then - str=str..Format("\nTrain arrived\nto last station\n%s",currEn) - if currR then str = str..",\nexit to the right side" end - end - elseif arr then - str = curr or "..." - if currR then str = str..",\nвыход на правую сторону" end - if currEn~="" then - str = str.."\n%y"..currEn.." station" - if currR then str = str..",\nexit to the right side" end - end + local white = Color(255,255,255) + local yellow = Color(255,235,100) + local green = Color(50,120,50) + local red = Color(255,65,85) + local blue = Color(40,60,255) - str = str..Format("\nСледующая станция\n%s",nxt) - if nxtR then str = str..",\nвыход на правую сторону" end - if special~="" then - if special:sub(1,2) == "%c" then str = str.."," end - str = str.."\n"..special - end - if nxtEn~="" then - str = str..Format("\n%%yNext station is\n%s",nxtEn) - if nxtR then str = str..",\nexit to the right side" end - end - elseif not arr and (self.Closing or closing) then - str = Format("%%rДвери закрываются\n%%yСледующая станция\n%s",nxt) - if nxtR then str = str..",\nвыход на правую сторону" end - if nxtEn~="" then - str = str..Format("\nNext station is\n%s",nxtEn) - if nxtR then str = str..",\nexit to the right side" end - end - if special~="" then - str = str.."\n"..special - end - else - str = "." - end - local tbl = string.Explode("\n",str) + local fontTop = "Metrostroi_BIT1" + local fontMain = "Metrostroi_BIT2" + local fontBottom = "Metrostroi_BIT3" + function TRAIN_SYSTEM:BIT(Train) + local state = Train:GetNW2Int("BIT:State",0) + if state == 0 then return end + surface.SetDrawColor(20,10,20) + surface.DrawRect(0,0,1024,192) - local otime = CurTime()+Train:GetNW2Int("TickersRandom",0)/10 - if self.OldArr ~= arr then - self.OldArr = arr - self.TimerCorrection = -otime + if state > 0 then + local showTime = Train:GetNW2Bool("BIT:Time") + local leftHeaderText = Train:GetNW2String("BIT:TextLeft","< ") + local rightHeaderText = Train:GetNW2String("BIT:TextRight"," >") + + if state == 1 then + local bitText = Train:GetNW2String("BIT:Text","---") + local yellowText = bitText:find("%%y") + local greenText = bitText:find("%%g") + local redText = bitText:find("%%r") + local blueText = bitText:find("%%b") + surface.SetFont(fontMain) + if yellowText then + surface.SetTextColor(yellow:Unpack()) + bitText = bitText:sub(yellowText+2) + elseif greenText then + surface.SetTextColor(green:Unpack()) + bitText = bitText:sub(greenText+2) + elseif redText then + surface.SetTextColor(red:Unpack()) + bitText = bitText:sub(redText+2) + elseif blueText then + surface.SetTextColor(blue:Unpack()) + bitText = bitText:sub(blueText+2) + else + surface.SetTextColor(white:Unpack()) + end + + drawText(bitText,512,48,TEXT_ALIGN_CENTER) + + -- TODO: Задел на предупредительные сообщения + draw.SimpleText("---",fontBottom,512,168, white,TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) + elseif state == 2 then + local ipNW2 = Train:GetNW2Int("BIT:IP",0) + local showIP = getBitValue(ipNW2,0,1) > 0 + local IP = getBitValue(ipNW2,1,8) + + draw.SimpleText(showIP and "ip = 192.168.5."..IP or "ООО “НПП “Сармат”",fontMain,512,100,yellow,TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) + + draw.SimpleText("Продукция ООО “НПП “Сармат”",fontBottom,501,168, Color(50,120,50),TEXT_ALIGN_RIGHT,TEXT_ALIGN_CENTER) + draw.SimpleText("* (с) 2014-2022, г. Ростов-на-Дону",fontBottom,508,168,white,TEXT_ALIGN_LEFT,TEXT_ALIGN_CENTER) end - local ctime = otime+self.TimerCorrection - local time = math.floor(ctime%(#tbl*3)/3)+1 - if not self.Closing and closing and time>1 then self.Closing = true end - if time==1 and not closing and self.Closing then - self.Closing = false + + local leftHeaderBorder = draw.SimpleText(leftHeaderText,fontTop,0,26,white,TEXT_ALIGN_LEFT,TEXT_ALIGN_CENTER) + local rightHeaderBorder = 1024-draw.SimpleText(rightHeaderText,fontTop,1024,26,white,TEXT_ALIGN_RIGHT,TEXT_ALIGN_CENTER) + + if showTime then + local d = os.date("!*t",Metrostroi.GetSyncTime()) + local time = Format("%d %s, %s, %02d:%02d",d.day,tMonth[d.month],tDay[d.wday],d.hour,d.min) + local timeW = surface.GetTextSize(time) + local timeX = math.max(math.min(512-timeW/2,rightHeaderBorder-timeW-8),leftHeaderBorder+8) + surface.SetTextColor(yellow:Unpack()) + drawText(time,timeX,-1) end - local message = tbl[time] - if message:find("%%y") or time==1 then self.Color = nil end - if message:find("%%r") then self.Color = Color(220,65,85) end - if message:find("%%g") then self.Color = Color(50,120,80) end - draw.SimpleText(message:gsub("%%[rgyc]",""),"Metrostroi_TNR60",300,64, self.Color or Color(245,235,170),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER) - --local prevStation = stbl[line][path and st+1 or st-1] - if arr and prev~="" then draw.SimpleText("< "..prev,"Metrostroi_TNR30",10,16, Color(200,200,200),TEXT_ALIGN_LEFT,TEXT_ALIGN_CENTER) end - --local nextStation = stbl[line][path and st-1 or st+1] - if nxt~="" then draw.SimpleText(nxt.." >","Metrostroi_TNR30",586,16, Color(200,200,200),TEXT_ALIGN_RIGHT,TEXT_ALIGN_CENTER) end + elseif state == -2 then + surface.SetDrawColor(255,255,255) + surface.DrawRect(0,0,1024,192) + end + end end diff --git a/materials/models/metrostroi_train/81-722/screens/sarmat_upo/ann_frame.vmt b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/ann_frame.vmt new file mode 100644 index 0000000..448281e --- /dev/null +++ b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/ann_frame.vmt @@ -0,0 +1,8 @@ +"UnlitGeneric" +{ + $basetexture models/metrostroi_train/81-722/screens/sarmat_upo/ann_frame + $nolod 1 + $ignorez 1 + $vertexcolor 1 + $vertexalpha 1 +} diff --git a/materials/models/metrostroi_train/81-722/screens/sarmat_upo/ann_frame.vtf b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/ann_frame.vtf new file mode 100644 index 0000000..37ffe23 --- /dev/null +++ b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/ann_frame.vtf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2adac6283ecd10b897d204ee7a59548aa00c36e54839342e49cbb337d5e1bec2 +size 524368 diff --git a/materials/models/metrostroi_train/81-722/screens/sarmat_upo/bmts.vmt b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/bmts.vmt new file mode 100644 index 0000000..36ef0af --- /dev/null +++ b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/bmts.vmt @@ -0,0 +1,8 @@ +"UnlitGeneric" +{ + $basetexture models/metrostroi_train/81-722/screens/sarmat_upo/bmts + $nolod 1 + $ignorez 1 + $vertexcolor 1 + $vertexalpha 1 +} diff --git a/materials/models/metrostroi_train/81-722/screens/sarmat_upo/bmts.vtf b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/bmts.vtf new file mode 100644 index 0000000..2d1fc55 --- /dev/null +++ b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/bmts.vtf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:429ad2450bca789b31fa687e83211e6659304d56e16bcae2e09c6b00cec2c2c3 +size 65616 diff --git a/materials/models/metrostroi_train/81-722/screens/sarmat_upo/cam_frame.vmt b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/cam_frame.vmt new file mode 100644 index 0000000..7f6155a --- /dev/null +++ b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/cam_frame.vmt @@ -0,0 +1,8 @@ +"UnlitGeneric" +{ + $basetexture models/metrostroi_train/81-722/screens/sarmat_upo/cam_frame + $nolod 1 + $ignorez 1 + $vertexcolor 1 + $vertexalpha 1 +} diff --git a/materials/models/metrostroi_train/81-722/screens/sarmat_upo/cam_frame.vtf b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/cam_frame.vtf new file mode 100644 index 0000000..731a4dd --- /dev/null +++ b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/cam_frame.vtf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ab428a9e5f758afe82147baee7efb92ce21011320d67d24cf63425d7f6ec103f +size 1048656 diff --git a/materials/models/metrostroi_train/81-722/screens/sarmat_upo/grub.vmt b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/grub.vmt new file mode 100644 index 0000000..39cc640 --- /dev/null +++ b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/grub.vmt @@ -0,0 +1,8 @@ +"UnlitGeneric" +{ + $basetexture models/metrostroi_train/81-722/screens/sarmat_upo/grub + $nolod 1 + $ignorez 1 + $vertexcolor 1 + $vertexalpha 1 +} diff --git a/materials/models/metrostroi_train/81-722/screens/sarmat_upo/grub.vtf b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/grub.vtf new file mode 100644 index 0000000..e122df1 --- /dev/null +++ b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/grub.vtf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2c1c56e1a54413865c1f944b699ea10e7fde07e664fcb95607e7c613cffcbcd7 +size 1048656 diff --git a/materials/models/metrostroi_train/81-722/screens/sarmat_upo/line_frame.vmt b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/line_frame.vmt new file mode 100644 index 0000000..7dc6a0b --- /dev/null +++ b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/line_frame.vmt @@ -0,0 +1,8 @@ +"UnlitGeneric" +{ + $basetexture models/metrostroi_train/81-722/screens/sarmat_upo/line_frame + $nolod 1 + $ignorez 1 + $vertexcolor 1 + $vertexalpha 1 +} diff --git a/materials/models/metrostroi_train/81-722/screens/sarmat_upo/line_frame.vtf b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/line_frame.vtf new file mode 100644 index 0000000..314fef8 --- /dev/null +++ b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/line_frame.vtf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2cc6e502ec003fefbee1d4e86b761e979acb99544c55e0ecf5a0b35a6d840e82 +size 4176 diff --git a/materials/models/metrostroi_train/81-722/screens/sarmat_upo/list_cursor.vmt b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/list_cursor.vmt new file mode 100644 index 0000000..76502d3 --- /dev/null +++ b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/list_cursor.vmt @@ -0,0 +1,8 @@ +"UnlitGeneric" +{ + $basetexture models/metrostroi_train/81-722/screens/sarmat_upo/list_cursor + $nolod 1 + $ignorez 1 + $vertexcolor 1 + $vertexalpha 1 +} diff --git a/materials/models/metrostroi_train/81-722/screens/sarmat_upo/list_cursor.vtf b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/list_cursor.vtf new file mode 100644 index 0000000..4c3e596 --- /dev/null +++ b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/list_cursor.vtf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:45fde20eb9313971dfc76d386ece2929340332d58b26df4724be4e9d89c5c595 +size 16464 diff --git a/materials/models/metrostroi_train/81-722/screens/sarmat_upo/sarmat_logo.vmt b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/sarmat_logo.vmt new file mode 100644 index 0000000..7d3b397 --- /dev/null +++ b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/sarmat_logo.vmt @@ -0,0 +1,8 @@ +"UnlitGeneric" +{ + $basetexture models/metrostroi_train/81-722/screens/sarmat_upo/sarmat_logo + $nolod 1 + $ignorez 1 + $vertexcolor 1 + $vertexalpha 1 +} diff --git a/materials/models/metrostroi_train/81-722/screens/sarmat_upo/sarmat_logo.vtf b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/sarmat_logo.vtf new file mode 100644 index 0000000..84b0b24 --- /dev/null +++ b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/sarmat_logo.vtf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c9cb7869f904bc28ba2eb4981ae4d6f0180ecee11aa12ff247d8e939720c555a +size 524368 diff --git a/materials/models/metrostroi_train/81-722/screens/sarmat_upo/tnm.vmt b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/tnm.vmt new file mode 100644 index 0000000..18f977b --- /dev/null +++ b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/tnm.vmt @@ -0,0 +1,8 @@ +"UnlitGeneric" +{ + $basetexture models/metrostroi_train/81-722/screens/sarmat_upo/tnm + $nolod 1 + $ignorez 1 + $vertexcolor 1 + $vertexalpha 1 +} diff --git a/materials/models/metrostroi_train/81-722/screens/sarmat_upo/tnm.vtf b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/tnm.vtf new file mode 100644 index 0000000..ca46ed4 --- /dev/null +++ b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/tnm.vtf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:22dcd8f155dff870ab445593cd3070cdb1277163e5a693440aad616cd6f9d57f +size 32848 diff --git a/materials/models/metrostroi_train/81-722/screens/sarmat_upo/traintrain_msg.vmt b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/traintrain_msg.vmt new file mode 100644 index 0000000..6cf9c1f --- /dev/null +++ b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/traintrain_msg.vmt @@ -0,0 +1,8 @@ +"UnlitGeneric" +{ + $basetexture models/metrostroi_train/81-722/screens/sarmat_upo/traintrain_msg + $nolod 1 + $ignorez 1 + $vertexcolor 1 + $vertexalpha 1 +} diff --git a/materials/models/metrostroi_train/81-722/screens/sarmat_upo/traintrain_msg.vtf b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/traintrain_msg.vtf new file mode 100644 index 0000000..cfe930d --- /dev/null +++ b/materials/models/metrostroi_train/81-722/screens/sarmat_upo/traintrain_msg.vtf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0021dfe62962a5014c1eff7eb3fc0ec320748a1040d675413a64d12ed85c15ba +size 131152 diff --git a/models/metrostroi_train/81-722/722_cabine.dx80.vtx b/models/metrostroi_train/81-722/722_cabine.dx80.vtx new file mode 100644 index 0000000..eec24ba --- /dev/null +++ b/models/metrostroi_train/81-722/722_cabine.dx80.vtx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e984e9f59191cea6f851338224d6f75d36072440da7abe5511bf29de2f25c006 +size 665876 diff --git a/models/metrostroi_train/81-722/722_cabine.dx90.vtx b/models/metrostroi_train/81-722/722_cabine.dx90.vtx new file mode 100644 index 0000000..7975fef --- /dev/null +++ b/models/metrostroi_train/81-722/722_cabine.dx90.vtx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4f674f316a966fa5eef7ae22972c6c0b63ed9b4ab7600e42c0a6f91a529704de +size 665876 diff --git a/models/metrostroi_train/81-722/722_cabine.mdl b/models/metrostroi_train/81-722/722_cabine.mdl new file mode 100644 index 0000000..8888375 --- /dev/null +++ b/models/metrostroi_train/81-722/722_cabine.mdl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c8039506ca82bb099b240746bc93cdfb289f95430265fd4f59cc25cbe5a2bbe5 +size 2728 diff --git a/models/metrostroi_train/81-722/722_cabine.sw.vtx b/models/metrostroi_train/81-722/722_cabine.sw.vtx new file mode 100644 index 0000000..6955220 --- /dev/null +++ b/models/metrostroi_train/81-722/722_cabine.sw.vtx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8813a61c27a7e5ad7c51d572b49a73bfa75409ccd90ab923abf6fbe2f544c349 +size 665828 diff --git a/models/metrostroi_train/81-722/722_cabine.vvd b/models/metrostroi_train/81-722/722_cabine.vvd new file mode 100644 index 0000000..610d4f9 --- /dev/null +++ b/models/metrostroi_train/81-722/722_cabine.vvd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fc8412e5475d8e7cd09a7328f835de86ef5fb9db1ed6ac20f09442a8e423ff6f +size 2717584 diff --git a/models/metrostroi_train/81-722/722_salon1.dx80.vtx b/models/metrostroi_train/81-722/722_salon1.dx80.vtx new file mode 100644 index 0000000..a0752ba --- /dev/null +++ b/models/metrostroi_train/81-722/722_salon1.dx80.vtx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b4a8eb17d7643fecd0bf1924e787bedf625a880613b3bfc8393207852648585b +size 575056 diff --git a/models/metrostroi_train/81-722/722_salon1.dx90.vtx b/models/metrostroi_train/81-722/722_salon1.dx90.vtx new file mode 100644 index 0000000..8ff3928 --- /dev/null +++ b/models/metrostroi_train/81-722/722_salon1.dx90.vtx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:63660fe0a6fb452bc4a18f5216671e9b81501a5be379baeb0580bfcb9797c72a +size 575056 diff --git a/models/metrostroi_train/81-722/722_salon1.mdl b/models/metrostroi_train/81-722/722_salon1.mdl new file mode 100644 index 0000000..ba02be3 --- /dev/null +++ b/models/metrostroi_train/81-722/722_salon1.mdl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:37f75a1134fd631cc08f237c6b1ba592dfe90cb9907306c7ee93e21676c0a8e6 +size 1768 diff --git a/models/metrostroi_train/81-722/722_salon1.sw.vtx b/models/metrostroi_train/81-722/722_salon1.sw.vtx new file mode 100644 index 0000000..0bf6e06 --- /dev/null +++ b/models/metrostroi_train/81-722/722_salon1.sw.vtx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a7367cf88e4e52ae71f6397cd7028a42929dca151c2567b605d4ff734f64e6c7 +size 575040 diff --git a/models/metrostroi_train/81-722/722_salon1.vvd b/models/metrostroi_train/81-722/722_salon1.vvd new file mode 100644 index 0000000..619a5f0 --- /dev/null +++ b/models/metrostroi_train/81-722/722_salon1.vvd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4eec518608626bb58bc5c176da8c5beee28332296dbe6b690346439195e681f6 +size 2123840 diff --git a/models/metrostroi_train/81-722/723_salon1.dx80.vtx b/models/metrostroi_train/81-722/723_salon1.dx80.vtx new file mode 100644 index 0000000..20d0cdd --- /dev/null +++ b/models/metrostroi_train/81-722/723_salon1.dx80.vtx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f828a466cb56c412ebccb563565a50dcb55c5b0df455a960481498bdd4b6d90d +size 591581 diff --git a/models/metrostroi_train/81-722/723_salon1.dx90.vtx b/models/metrostroi_train/81-722/723_salon1.dx90.vtx new file mode 100644 index 0000000..b035f9d --- /dev/null +++ b/models/metrostroi_train/81-722/723_salon1.dx90.vtx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:928b1316f6b830276c83e8f525a4903e42a6d602fc24f83f29850d039b5c4536 +size 591581 diff --git a/models/metrostroi_train/81-722/723_salon1.mdl b/models/metrostroi_train/81-722/723_salon1.mdl new file mode 100644 index 0000000..9b7529e --- /dev/null +++ b/models/metrostroi_train/81-722/723_salon1.mdl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9660269b28b7480cc074dd0a03a905703baed4955893d17f153dec0a7cac414d +size 1768 diff --git a/models/metrostroi_train/81-722/723_salon1.sw.vtx b/models/metrostroi_train/81-722/723_salon1.sw.vtx new file mode 100644 index 0000000..e98e16a --- /dev/null +++ b/models/metrostroi_train/81-722/723_salon1.sw.vtx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:99230a6675a79c4d552dc19143a38fc6b67ea5d5d168adda8ed974ff1d429ef0 +size 591573 diff --git a/models/metrostroi_train/81-722/723_salon1.vvd b/models/metrostroi_train/81-722/723_salon1.vvd new file mode 100644 index 0000000..9539218 --- /dev/null +++ b/models/metrostroi_train/81-722/723_salon1.vvd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3ffd77621a0231f6cf90b81ad91c6a20d736ac5823eabad4a02b1ae30508d26d +size 2399232 diff --git a/resource/fonts/dejavu_sans.ttf b/resource/fonts/dejavu_sans.ttf new file mode 100644 index 0000000..356575d --- /dev/null +++ b/resource/fonts/dejavu_sans.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7da195a74c55bef988d0d48f9508bd5d849425c1770dba5d7bfc6ce9ed848954 +size 757076 diff --git a/resource/fonts/dejavu_sans_license.txt b/resource/fonts/dejavu_sans_license.txt new file mode 100644 index 0000000..df52c17 --- /dev/null +++ b/resource/fonts/dejavu_sans_license.txt @@ -0,0 +1,187 @@ +Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. +Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below) + + +Bitstream Vera Fonts Copyright +------------------------------ + +Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is +a trademark of Bitstream, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of the fonts accompanying this license ("Fonts") and associated +documentation files (the "Font Software"), to reproduce and distribute the +Font Software, including without limitation the rights to use, copy, merge, +publish, distribute, and/or sell copies of the Font Software, and to permit +persons to whom the Font Software is furnished to do so, subject to the +following conditions: + +The above copyright and trademark notices and this permission notice shall +be included in all copies of one or more of the Font Software typefaces. + +The Font Software may be modified, altered, or added to, and in particular +the designs of glyphs or characters in the Fonts may be modified and +additional glyphs or characters may be added to the Fonts, only if the fonts +are renamed to names not containing either the words "Bitstream" or the word +"Vera". + +This License becomes null and void to the extent applicable to Fonts or Font +Software that has been modified and is distributed under the "Bitstream +Vera" names. + +The Font Software may be sold as part of a larger software package but no +copy of one or more of the Font Software typefaces may be sold by itself. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, +TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME +FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING +ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE +FONT SOFTWARE. + +Except as contained in this notice, the names of Gnome, the Gnome +Foundation, and Bitstream Inc., shall not be used in advertising or +otherwise to promote the sale, use or other dealings in this Font Software +without prior written authorization from the Gnome Foundation or Bitstream +Inc., respectively. For further information, contact: fonts at gnome dot +org. + +Arev Fonts Copyright +------------------------------ + +Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of the fonts accompanying this license ("Fonts") and +associated documentation files (the "Font Software"), to reproduce +and distribute the modifications to the Bitstream Vera Font Software, +including without limitation the rights to use, copy, merge, publish, +distribute, and/or sell copies of the Font Software, and to permit +persons to whom the Font Software is furnished to do so, subject to +the following conditions: + +The above copyright and trademark notices and this permission notice +shall be included in all copies of one or more of the Font Software +typefaces. + +The Font Software may be modified, altered, or added to, and in +particular the designs of glyphs or characters in the Fonts may be +modified and additional glyphs or characters may be added to the +Fonts, only if the fonts are renamed to names not containing either +the words "Tavmjong Bah" or the word "Arev". + +This License becomes null and void to the extent applicable to Fonts +or Font Software that has been modified and is distributed under the +"Tavmjong Bah Arev" names. + +The Font Software may be sold as part of a larger software package but +no copy of one or more of the Font Software typefaces may be sold by +itself. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL +TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +Except as contained in this notice, the name of Tavmjong Bah shall not +be used in advertising or otherwise to promote the sale, use or other +dealings in this Font Software without prior written authorization +from Tavmjong Bah. For further information, contact: tavmjong @ free +. fr. + +TeX Gyre DJV Math +----------------- +Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. + +Math extensions done by B. Jackowski, P. Strzelczyk and P. Pianowski +(on behalf of TeX users groups) are in public domain. + +Letters imported from Euler Fraktur from AMSfonts are (c) American +Mathematical Society (see below). +Bitstream Vera Fonts Copyright +Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera +is a trademark of Bitstream, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of the fonts accompanying this license (“Fonts”) and associated +documentation +files (the “Font Software”), to reproduce and distribute the Font Software, +including without limitation the rights to use, copy, merge, publish, +distribute, +and/or sell copies of the Font Software, and to permit persons to whom +the Font Software is furnished to do so, subject to the following +conditions: + +The above copyright and trademark notices and this permission notice +shall be +included in all copies of one or more of the Font Software typefaces. + +The Font Software may be modified, altered, or added to, and in particular +the designs of glyphs or characters in the Fonts may be modified and +additional +glyphs or characters may be added to the Fonts, only if the fonts are +renamed +to names not containing either the words “Bitstream” or the word “Vera”. + +This License becomes null and void to the extent applicable to Fonts or +Font Software +that has been modified and is distributed under the “Bitstream Vera” +names. + +The Font Software may be sold as part of a larger software package but +no copy +of one or more of the Font Software typefaces may be sold by itself. + +THE FONT SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, +TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME +FOUNDATION +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, +SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN +ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR +INABILITY TO USE +THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. +Except as contained in this notice, the names of GNOME, the GNOME +Foundation, +and Bitstream Inc., shall not be used in advertising or otherwise to promote +the sale, use or other dealings in this Font Software without prior written +authorization from the GNOME Foundation or Bitstream Inc., respectively. +For further information, contact: fonts at gnome dot org. + +AMSFonts (v. 2.2) copyright + +The PostScript Type 1 implementation of the AMSFonts produced by and +previously distributed by Blue Sky Research and Y&Y, Inc. are now freely +available for general use. This has been accomplished through the +cooperation +of a consortium of scientific publishers with Blue Sky Research and Y&Y. +Members of this consortium include: + +Elsevier Science IBM Corporation Society for Industrial and Applied +Mathematics (SIAM) Springer-Verlag American Mathematical Society (AMS) + +In order to assure the authenticity of these fonts, copyright will be +held by +the American Mathematical Society. This is not meant to restrict in any way +the legitimate use of the fonts, such as (but not limited to) electronic +distribution of documents containing these fonts, inclusion of these fonts +into other public domain or commercial font collections or computer +applications, use of the outline data to create derivative fonts and/or +faces, etc. However, the AMS does require that the AMS copyright notice be +removed from any derivative versions of the fonts which have been altered in +any way. In addition, to ensure the fidelity of TeX documents using Computer +Modern fonts, Professor Donald Knuth, creator of the Computer Modern faces, +has requested that any alterations which yield different font metrics be +given a different name. + +$Id$ diff --git a/resource/fonts/liberationserif-regular.ttf b/resource/fonts/liberationserif-regular.ttf new file mode 100644 index 0000000..a988fef --- /dev/null +++ b/resource/fonts/liberationserif-regular.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:058ea80864aef09a23f45cbec2bb5400bc3dfbdea01c3f10538a21fcb497fb74 +size 393576 diff --git a/resource/fonts/liberationserif_license.txt b/resource/fonts/liberationserif_license.txt new file mode 100644 index 0000000..aba73e8 --- /dev/null +++ b/resource/fonts/liberationserif_license.txt @@ -0,0 +1,102 @@ +Digitized data copyright (c) 2010 Google Corporation + with Reserved Font Arimo, Tinos and Cousine. +Copyright (c) 2012 Red Hat, Inc. + with Reserved Font Name Liberation. + +This Font Software is licensed under the SIL Open Font License, +Version 1.1. + +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 + +PREAMBLE The goals of the Open Font License (OFL) are to stimulate +worldwide development of collaborative font projects, to support the font +creation efforts of academic and linguistic communities, and to provide +a free and open framework in which fonts may be shared and improved in +partnership with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. +The fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply to +any document created using the fonts or their derivatives. + + + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. +This may include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components +as distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting ? in part or in whole ? +any of the components of the Original Version, by changing formats or +by porting the Font Software to a new environment. + +"Author" refers to any designer, engineer, programmer, technical writer +or other person who contributed to the Font Software. + + +PERMISSION & CONDITIONS + +Permission is hereby granted, free of charge, to any person obtaining a +copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components,in + Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, + redistributed and/or sold with any software, provided that each copy + contains the above copyright notice and this license. These can be + included either as stand-alone text files, human-readable headers or + in the appropriate machine-readable metadata fields within text or + binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font + Name(s) unless explicit written permission is granted by the + corresponding Copyright Holder. This restriction only applies to the + primary font name as presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font + Software shall not be used to promote, endorse or advertise any + Modified Version, except to acknowledge the contribution(s) of the + Copyright Holder(s) and the Author(s) or with their explicit written + permission. + +5) The Font Software, modified or unmodified, in part or in whole, must + be distributed entirely under this license, and must not be distributed + under any other license. The requirement for fonts to remain under + this license does not apply to any document created using the Font + Software. + + + +TERMINATION +This license becomes null and void if any of the above conditions are not met. + + + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER +DEALINGS IN THE FONT SOFTWARE. + diff --git a/resource/fonts/ubuntu-c.ttf b/resource/fonts/ubuntu-c.ttf new file mode 100644 index 0000000..c17f562 --- /dev/null +++ b/resource/fonts/ubuntu-c.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6c1f68d2e85832feae9ea30d2a6c0ea71ea623e8ea342bf00a414f6493ccf720 +size 350444 diff --git a/resource/fonts/ubuntu-c_license.txt b/resource/fonts/ubuntu-c_license.txt new file mode 100644 index 0000000..ae78a8f --- /dev/null +++ b/resource/fonts/ubuntu-c_license.txt @@ -0,0 +1,96 @@ +------------------------------- +UBUNTU FONT LICENCE Version 1.0 +------------------------------- + +PREAMBLE +This licence allows the licensed fonts to be used, studied, modified and +redistributed freely. The fonts, including any derivative works, can be +bundled, embedded, and redistributed provided the terms of this licence +are met. The fonts and derivatives, however, cannot be released under +any other licence. The requirement for fonts to remain under this +licence does not require any document created using the fonts or their +derivatives to be published under this licence, as long as the primary +purpose of the document is not to be a vehicle for the distribution of +the fonts. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this licence and clearly marked as such. This may +include source files, build scripts and documentation. + +"Original Version" refers to the collection of Font Software components +as received under this licence. + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to +a new environment. + +"Copyright Holder(s)" refers to all individuals and companies who have a +copyright ownership of the Font Software. + +"Substantially Changed" refers to Modified Versions which can be easily +identified as dissimilar to the Font Software by users of the Font +Software comparing the Original Version with the Modified Version. + +To "Propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification and with or without charging +a redistribution fee), making available to the public, and in some +countries other activities as well. + +PERMISSION & CONDITIONS +This licence does not grant any rights under trademark law and all such +rights are reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of the Font Software, to propagate the Font Software, subject to +the below conditions: + +1) Each copy of the Font Software must contain the above copyright +notice and this licence. These can be included either as stand-alone +text files, human-readable headers or in the appropriate machine- +readable metadata fields within text or binary files as long as those +fields can be easily viewed by the user. + +2) The font name complies with the following: +(a) The Original Version must retain its name, unmodified. +(b) Modified Versions which are Substantially Changed must be renamed to +avoid use of the name of the Original Version or similar names entirely. +(c) Modified Versions which are not Substantially Changed must be +renamed to both (i) retain the name of the Original Version and (ii) add +additional naming elements to distinguish the Modified Version from the +Original Version. The name of such Modified Versions must be the name of +the Original Version, with "derivative X" where X represents the name of +the new work, appended to that name. + +3) The name(s) of the Copyright Holder(s) and any contributor to the +Font Software shall not be used to promote, endorse or advertise any +Modified Version, except (i) as required by this licence, (ii) to +acknowledge the contribution(s) of the Copyright Holder(s) or (iii) with +their explicit written permission. + +4) The Font Software, modified or unmodified, in part or in whole, must +be distributed entirely under this licence, and must not be distributed +under any other licence. The requirement for fonts to remain under this +licence does not affect any document created using the Font Software, +except any version of the Font Software extracted from a document +created using the Font Software may only be distributed under this +licence. + +TERMINATION +This licence becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF +COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER +DEALINGS IN THE FONT SOFTWARE. diff --git a/sound/subway_trains/722/door_alarm_end.mp3 b/sound/subway_trains/722/door_alarm_end.mp3 new file mode 100644 index 0000000..b02678f --- /dev/null +++ b/sound/subway_trains/722/door_alarm_end.mp3 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e09de32c9c3043c4f717b4be0b81644ce49b54b5732aba0f599c1053d9bb80cb +size 33649 diff --git a/sound/subway_trains/722/door_alarm_loop.wav b/sound/subway_trains/722/door_alarm_loop.wav new file mode 100644 index 0000000..3faf524 --- /dev/null +++ b/sound/subway_trains/722/door_alarm_loop.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:95d52328f9d5f14adcdb2671b53f77a30c5fc485357ee5b4b209728bc4f37b99 +size 185596 diff --git a/sound/subway_trains/722/door_alarm_start.mp3 b/sound/subway_trains/722/door_alarm_start.mp3 new file mode 100644 index 0000000..2fc7888 --- /dev/null +++ b/sound/subway_trains/722/door_alarm_start.mp3 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:efd0a9ebb49dc1257cde6b74f5502d86b003a5959102f183ddbf1a2876f10364 +size 33649 diff --git a/sound/subway_trains/722/sarmat_start.mp3 b/sound/subway_trains/722/sarmat_start.mp3 new file mode 100644 index 0000000..fe447c6 --- /dev/null +++ b/sound/subway_trains/722/sarmat_start.mp3 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cd861b90f221a813dd603d0e10deca03b67e8710f563138ac2daf176d0b12759 +size 60606