1
0
mirror of https://github.com/metrostroi-repo/MetrostroiAddon.git synced 2026-05-02 00:42:29 +00:00
Files
MetrostroiAddon/lua/metrostroi/systems/sys_81_722_electric.lua
kosmik641 c06ccbe776 81-722.
Перенос логики кнопок дверей в Panel для электрики
Триггеры для БМЦИКа от БУКП
Поправлена логика 15 провода
Фикс работы дверей от резервного управления
2025-05-30 12:57:31 +03:00

336 lines
14 KiB
Lua

--------------------------------------------------------------------------------
-- 81-722 electric schemes
--------------------------------------------------------------------------------
-- Copyright (C) 2013-2018 Metrostroi Team & FoxWorks Aerospace s.r.o.
-- Contains proprietary code. See license.txt for additional information.
--------------------------------------------------------------------------------
Metrostroi.DefineSystem("81_722_Electric")
TRAIN_SYSTEM.DontAccelerateSimulation = false
local function Clamp(val,min,max)
return math.max(min,math.min(max,val))
end
TRAIN_SYSTEM.T722 = 0
TRAIN_SYSTEM.T723 = 1
TRAIN_SYSTEM.T724 = 2
function TRAIN_SYSTEM:Initialize()
self.Type = self.Type or self.T722
self.HaveBUKP = 0--self.HaveBUKP or self.Type==self.T722 and 1 or 0
self.HaveAsyncInverter = 0--self.HaveAsyncInverter or self.Type<self.T724 and 1 or 0
self.Train:LoadSystem("Battery","Relay","")
self.Train:LoadSystem("BatteryOn","Relay",nil,{bass=true,open_time=0,close_time=0.7})
self.Train:LoadSystem("BatteryOff","Relay",nil,{bass=true,open_time=0,close_time=0.6})
self.Power = 0
self.BatterySound = 0
self.CabActive = 0
self.CabActiveVRU = 0
self.Emer = 0
self.BUFT =0
self.AsyncEmer = 0
self.AsyncActive = 0
self.Reverser = 0
self.BTBPower = 0
self.BTB = 0
self.Main750V = 0
self.Aux750V = 0
self.Power750V = 0
self.MK = 0
self.PSN = 0
self.Vent1 = 0
self.Vent2 = 0
self.LightsHV = 0
self.DisablePant = 0
self.V1 = 0
self.V6Power = 0
self.LSD = 0
self.Recurperation = 0
self.Iexit = 0
self.Chopper = 0
self.ElectricEnergyUsed = 0
self.ElectricEnergyDissipated = 0
end
function TRAIN_SYSTEM:Inputs()
return { "Type"}
end
function TRAIN_SYSTEM:Outputs()
return {
"Main750V","Aux750V","Power750V",
"Type","HaveBUKP","HaveAsyncInverter","Power","BatterySound","CabActive","CabActiveVRU","Emer","BUFT","AsyncEmer","AsyncActive","Reverser","BTB","BTBPower","BARSPower","V6Power","LSD",
"PSN","Vent1","Vent2","MK","DisablePant","V1",
"Recurperation","Iexit","Chopper","ElectricEnergyUsed","ElectricEnergyDissipated","EnergyChange","Itotal"
}
end
function TRAIN_SYSTEM:TriggerInput(name,value)
if name == "Type" then
self.Type = value
self.HaveBUKP = self.Type==self.T722 and 1 or 0
self.HaveAsyncInverter = self.Type<self.T724 and 1 or 0
end
end
local S = {}
local function C(x) return x and 1 or 0 end
local min = math.min
local wires = {5,6,8,-8,9,12,13,15,19,24,26,32,33,34,36,50}
function TRAIN_SYSTEM:Think(dT)
local Train = self.Train
local Panel = Train.Panel
local BUKV = Train.BUKV
local W = Train.TrainWires
if not W then
W = {}
for _,v in ipairs(wires) do W[v] = 0 end
Train.TrainWires = W
end
for _,v in ipairs(wires) do W[v] = min(Train:ReadTrainWire(v),1) end
self.Main750V = Train.TR.Main750V
self.Aux750V = Train.TR.Main750V
self.Power750V = self.Main750V--*Train.BRU.Value
----------------------------------------------------------------------------
-- Some internal electric
----------------------------------------------------------------------------
local BO = min(1,Train.Battery.Value+W[50]*Train.SF31.Value)
self.Power = BO
if self.HaveBUKP > 0 then
Train:WriteTrainWire(5,Train.SF1.Value*(Train.BattOn.Value+BO*(1-Train.Battery.Value)))
Train:WriteTrainWire(6,BO*Train.SF1.Value*(Train.BattOff.Value+Train.BatteryOff.Value))
S["RU"] = BO*Train.SF4.Value*C(Train.VRU.Value==0)
self.CabActiveVRU = BO*C(Train.VRU.Value==2)*Train.SF2.Value
self.CabActive = BO*C(Train.VRU.Value>0)*((self.CabActiveVRU+Train.BUKP.Active)*Train.SF3.Value+S["RU"])*Train.SF2.Value
Panel.LRU = BO*(1-self.CabActive)
Panel.AVS = BO*Train.Pneumatic.SD2
Panel.EmergencyDriveL = S["RU"]
Panel.EmergencyBrakeTPlusL = S["RU"]
S["RV"] = BO*self.CabActive*Train.SF2.Value
Train:WriteTrainWire(4,S["RV"]*Train.SF21.Value)
Train:WriteTrainWire(3,0)
S["RVnE"] = BO*self.CabActive*Train.SF2.Value
Train:WriteTrainWire(12,math.max(S["RV"]*C(Train.KRO.Value==2)+S["RU"]))
Train:WriteTrainWire(13,S["RVnE"]*C(Train.KRO.Value==0))
Train:WriteTrainWire(36,BO*Train.SF3.Value*C(Train.VRU.Value >0)*self.CabActive)
Train:WriteTrainWire(34,S["RU"])
Train:WriteTrainWire(19,S["RU"]*(1-Train.Pneumatic.SD3)*Train.EmergencyDrive.Value)
Train:WriteTrainWire(27,BO*S["RU"])
Train:WriteTrainWire(29,self.BTB*S["RU"]*(C(Panel.Controller<=-2)+Train.EmergencyBrakeTPlus.Value))
Train:WriteTrainWire(30,self.BTB*S["RU"]*C(Panel.Controller<=-1))
Panel.V4 = (S["RVnE"]*C(Train.KRO.Value~=1)+S["RU"])*Train.SF6.Value
Train:WriteTrainWire(11,Panel.V4*Train.ParkingBrake.Value)
Train:WriteTrainWire(31,Panel.V4*(1-Train.ParkingBrake.Value))
Train:WriteTrainWire(-8,BO*min(1,(S["RV"]+S["RU"]))*Train.SF7.Value)
Train:WriteTrainWire(9,W[8]*(1-self.CabActive)*C(Train.VRU.Value==1)*Train.SF7.Value)
self.LSD = W[9]*Train.SF7.Value
S["V6m"] = min(1,Train.BARS.EPK*Train.RCARS.Value+(1-Train.RCARS.Value)*(Train.PB.Value+Train.VAH.Value))
local BTB = Panel.V4*(1-Train.Pneumatic.SD2)*S["V6m"]
--Train:WriteTrainWire(24,BTB*(1-Train.EmergencyBrake.Value))
--Train:WriteTrainWire(25,BTB == 0 and W[26] > 0 and W[24]*self.BTB or 0)
self.V6Power = BO*Train.SF5.Value*S["V6m"]
if BTB > 0 then
if self.BTBTimer == nil then self.BTBTimer = CurTime() end
if self.BTBTimer and CurTime()-self.BTBTimer>0.3 then self.BTBTimer = false end
else
self.BTBTimer = nil
end
self.BTBPower = BTB
self.BTB = min(1,(self.BTBTimer~=false and 1 or 0)+self.BTB*W[26])
if BTB > 0 and W[26]==0 and not self.TestTimer then
self.TestTimer = CurTime()
elseif W[26]>0 and self.TestTimer then
self.TestTimer = nil
end
S["NEmergencyBrake"] = (1-Train.EmergencyBrake.Value)*C(Panel.Controller~=-3)
Train:WriteTrainWire(26,(1-BTB)*W[24]*S["NEmergencyBrake"])
Train:WriteTrainWire(24,BTB*S["NEmergencyBrake"])
Train:WriteTrainWire(25,BTB*self.BTB*(self.KTR==3 and 0 or 1))
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
Panel.RC = Train.EmergencyRadioPower.Value
Panel.CabLights = (BO*Train.CabinLight.Value/2+Panel.RC*0.5--[[ *(0.5-Train.PanelLight.Value/4)--]] )*Train.SF25.Value
Panel.VPR1 = (BO+Panel.RC)*Train.SF14.Value
Panel.VPR2 = (BO+Panel.RC)*Train.SF15.Value
Panel.PanelLights = BO*Train.PanelLight.Value*Train.SF25.Value
Panel.Headlights1 = (S["RV"]+S["RU"])*C(Train.KRO.Value==2)*Train.SF22.Value*C(Train.Headlights.Value==1)
Panel.Headlights2 = (S["RV"]+S["RU"])*C(Train.KRO.Value==2)*Train.SF22.Value*C(Train.Headlights.Value==2)
Panel.RedLights = (BO*Train.SF22.Value+Train.VKF.Value*Train.SF23.Value)*(1-S["RVnE"]+C(Train.KRO.Value<2))
Panel.SOSD = S["RV"]*Train.SF7.Value*Train.SF24.Value*Train.BUKP.SOSD*(1-self.LSD)
Panel.BARSPower = BO*min(1,(Train.SF8.Value*C(Train.BARSMode.Value > 0)+Train.SF9.Value*C(Train.BARSMode.Value < 2))*Train.RCARS.Value)
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.BMCIK.UPOActive
Train:WriteTrainWire(15,BO*(Train.BMCIK.LineOut + Train.UPO.LineOut))
self.Emer = S["RU"]
end
S["DoorsP"] = BO*Train.SF36.Value
Train:WriteTrainWire(8,W[-8]*S["DoorsP"]*Train.S1.Value)
Panel.DoorsW = S["DoorsP"]*(1-Train.S1.Value)
Panel.BrW = BO*Train.SF36.Value*Train.Pneumatic.SD4
Panel.AnnouncerPlaying = W[15]
S["WagP"] = Train.Battery.Value*Train.SF33.Value
if self.HaveAsyncInverter > 0 then
local Async = Train.AsyncInverter
local HV = BO*C(550 < self.Aux750V and self.Aux750V < 975)
self.AsyncEmer = W[34]*Train.SF59.Value
self.AsyncActive = min(1,W[36]*Train.SF58.Value+self.AsyncEmer)
self.Reverser = self.AsyncActive*(W[12]-W[13])
Panel.GRP = BO*((1-Train.SF56.Value)+BUKV.DisableTP)
Async:TriggerInput("Power",BO*Train.SF56.Value*(1-BUKV.DisableTP))
local speed = math.abs(Async.Speed)
if self.AsyncEmer > 0 then
Async:TriggerInput("Drive",W[19])
Async:TriggerInput("Brake",0)
if W[19] > 0 then
Async:TriggerInput("TargetTorque",(1.0+Clamp(speed/15,0,1)-Clamp((speed-30)/38,0,2))*(3))
else
Async:TriggerInput("TargetTorque",0)
end
else
Async:TriggerInput("Drive",BUKV.Drive)
Async:TriggerInput("Brake",BUKV.Brake)
local command = (BUKV.Strength/100)*(BUKV.Drive-BUKV.Brake)
if command > 0 then
Async:TriggerInput("TargetTorque",(math.abs(command)^0.5)*(1.0+Clamp(speed/15,0,1)-Clamp((speed-30)/38,0,2))*(1+Train.Pneumatic.WeightLoadRatio*0.3))
elseif command < 0 then
Async:TriggerInput("TargetTorque",Clamp((speed-1)/4,0,1)*math.abs(command)*2.4*(1+Train.Pneumatic.WeightLoadRatio*0.3))
else
Async:TriggerInput("TargetTorque",0)
end
end
self.PSN = HV*(1-BUKV.DisablePSN)
self.LightsHV = min(1,self.PSN+self.LightsHV)*BUKV.EnableLights
if self.PSN == 0 then
if not self.PassLightsTimer then self.PassLightsTimer = CurTime() end
if self.PassLightsTimer and CurTime()-self.PassLightsTimer > 20 then self.LightsHV = 0 end
elseif self.PassLightsTimer then
self.PassLightsTimer = nil
end
Train:WriteTrainWire(32,self.LightsHV)
Train:WriteTrainWire(33,self.PSN)
self.MK = self.PSN*BUKV.EnableMK
self.DisablePant = BO*BUKV.DisablePant*Train.SF37.Value
self.EnergyChange = Async.Mode>0 and (Async.Current^2)*2.8 or 0
self.Itotal = Async.Current
--[[ if self.Main750V > 900 or Async.Mode>0 then
self.Recurperation = false
elseif self.Main750V < 875 and Async.Mode<0 then
end--]]
if Async.Mode<0 and Async.State>0 then
self.Recurperation = self.Main750V < 940 and 1 or 0
self.Iexit = self.Iexit+(-Async.Current*2*self.Recurperation-self.Iexit)*dT*2
--[[ if self.Main750V>550 then
self.Iexit = self.Iexit+(-Async.Current*2*self.Recurperation-self.Iexit)*dT*2
else
self.Iexit = 0
end--]]
self.Chopper = (self.Main750V>910 or self.Main750V<550) and 1 or 0
else
self.Recurperation = 0
self.Iexit = 0
self.Chopper = 0
end
--print(self.Recurperation,self.Iexit,self.Main750V)
self.ElectricEnergyUsed = self.ElectricEnergyUsed + math.max(0,self.EnergyChange)*dT
self.ElectricEnergyDissipated = self.ElectricEnergyDissipated + math.max(0,-self.EnergyChange)*dT
end
local vent = Train.BUKV.VentMode
self.Vent1 = (BO*C(vent==-1)+W[33]*C(vent>0))*Train.SF47.Value
self.Vent2 =W[33]*C(vent>1)*Train.SF48.Value
Panel.MainLights = W[32]*Train.SF45.Value*(1-BUKV.DisableLights)
Panel.EmergencyLights = S["WagP"]*Train.SF45.Value*Train.SF46.Value
self.BUFT = BO*Train.SF55.Value
Train.BatteryOn:TriggerInput("Set",W[5]*Train.SF32.Value)
Train.BatteryOff:TriggerInput("Set",W[6]*Train.SF32.Value)
local BatterySound = (1-Train.Battery.Value)*Train.BatteryOn.TargetValue+Train.Battery.Value*Train.BatteryOff.TargetValue
if BatterySound~=self.BatterySound then
self.BatterySound = BatterySound
if BatterySound>0 then Train:PlayOnce("battery_pneumo","bass",1) end
end
Train.Battery:TriggerInput("Close",Train.BatteryOn.Value)
Train.Battery:TriggerInput("Open",Train.BatteryOff.Value)
Train:WriteTrainWire(50,Train.Battery.Value)
Panel.PassSchemePowerL = BO*Train.SF34.Value
Panel.PassSchemePowerR = BO*Train.SF35.Value
--self.Train:LoadSystem("BatteryOn","Relay",nil,{open_time=0.6,close_time=8})
--self.Train:LoadSystem("BatteryOff","Relay",nil,{open_time=0.6,close_time=8})
--[[ --OU
Train:WriteTrainWire(34,P*(Train.RV["KRO1-2"]*Train.SF2.Value + Train.RV["KRR1-2"]*Train.SF3.Value))
--RU
Train:WriteTrainWire(36,Train.SF3.Value*Train.EmergencyControls.Value)
--XOD1
Train:WriteTrainWire(19,P*Train.RV["KRR7-8"]*Train.SF10.Value*Train.BARS.BTB*Train.EmerX1.Value)
--XOD2
Train:WriteTrainWire(45,P*Train.RV["KRR7-8"]*Train.SF10.Value*Train.BARS.BTB*Train.EmerX2.Value)
--ORIENTATION
--PARKING
Train:WriteTrainWire(11,P*Train.ParkingBrake.Value)
local KM1 = P*Train.SF6.Value*Train.RV["KRO11-12"]
local KM2 = P*Train.SF6.Value*Train.RV["KRO15-16"]
--REVERSER
Train:WriteTrainWire(12,P*(Train.RV["KRR3-4"]+KM1)*Train.SF11.Value)
Train:WriteTrainWire(13,P*(Train.RV["KRR9-10"]+KM2)*Train.SF11.Value)
--EMER BRAKE
--BTB
Train:WriteTrainWire(10,P*Train.EmergencyCompressor.Value)
Train:WriteTrainWire(40,P*Train.EmergencyDoors.Value)
Train:WriteTrainWire(39,P*Train.SF22.Value*Train.EmerCloseDoors.Value)
Train:WriteTrainWire(38,P*Train.SF21.Value*Train.DoorLeft.Value)
Train:WriteTrainWire(37,P*Train.SF21.Value*Train.DoorRight.Value)
--]]
end