AddCSLuaFile("cl_init.lua") AddCSLuaFile("shared.lua") 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", "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", "PSNToggle","BattOn","BattOff","TorecDoorUnlock", "PassLight","VKF","ParkingBrake","VRD","SOSDEnable","VAD","VAH","EmergencyRadioPower","RCARS", "MirrorHeating","DoorLeft2","DoorBack","EmergencyDrive","Microphone","DoorLeft1", "ARS","ALS","GlassWasher","EmergencyBrakeTPlus","EmergencyBrakeTPlusK","EmergencyBrake","Vigilance","DoorSelect","DoorRight", "PanelLight", "Ring", "K9", "K29", "EmergencyBrakeValve","UAVA", "FrontBrakeLineIsolation","FrontTrainLineIsolation", "RearBrakeLineIsolation","RearTrainLineIsolation", "PB", } -------------------------------------------------------------------------------- function ENT:Initialize() self.Plombs = { EmergencyBrakeTPlusK = true, VRU=true, VAH = true, VAD=true, EmergencyRadioPower = true, BARSMode = true, PantSC = true, RCARS = true, K9 = true, UAVA = true, Init=true, } -- Set model and initialize self:SetModel("models/metrostroi_train/81-722/81-722.mdl") self.BaseClass.Initialize(self) self:SetPos(self:GetPos() + Vector(0,0,140)) -- Create seat entities self.DriverSeat = self:CreateSeat("driver",Vector(450-2,11,-35+2)) self.InstructorsSeat = self:CreateSeat("instructor",Vector(440,42,-50),Angle(0,60,0),"models/vehicles/prisoner_pod_inner.mdl") self.InstructorsSeat2 = self:CreateSeat("instructor",Vector(420,12,-47),Angle(0,90,0),"models/vehicles/prisoner_pod_inner.mdl") self.InstructorsSeat3 = self:CreateSeat("instructor",Vector(428,-19,-50),Angle(0,120,0),"models/vehicles/prisoner_pod_inner.mdl") self.InstructorsSeat4 = self:CreateSeat("instructor",Vector(455,-30,-50),Angle(0,90,0),"models/vehicles/prisoner_pod_inner.mdl") -- Hide seats self.DriverSeat:SetRenderMode(RENDERMODE_TRANSALPHA) self.DriverSeat:SetColor(Color(0,0,0,0)) self.InstructorsSeat:SetRenderMode(RENDERMODE_TRANSALPHA) self.InstructorsSeat:SetColor(Color(0,0,0,0)) self.InstructorsSeat2:SetRenderMode(RENDERMODE_TRANSALPHA) self.InstructorsSeat2:SetColor(Color(0,0,0,0)) self.InstructorsSeat3:SetRenderMode(RENDERMODE_TRANSALPHA) self.InstructorsSeat3:SetColor(Color(0,0,0,0)) self.InstructorsSeat4:SetRenderMode(RENDERMODE_TRANSALPHA) self.InstructorsSeat4:SetColor(Color(0,0,0,0)) -- Create bogeys self.FrontBogey = self:CreateBogey(Vector( 322,0,-90),Angle(0,180,0),true,"722") self.RearBogey = self:CreateBogey(Vector(-333,0,-90),Angle(0,0,0),false,"722") self.FrontBogey:SetNWBool("Async",true) self.RearBogey:SetNWBool("Async",true) self.FrontBogey:SetNWFloat("SqualPitch",0.75) self.RearBogey:SetNWFloat("SqualPitch",0.75) self.FrontBogey:SetNWBool("DisableEngines",true) self.RearBogey:SetNWBool("DisableEngines",true) if Metrostroi.BogeyOldMap then self.FrontCouple = self:CreateCouple(Vector( 448-6,0,-77),Angle(0,0,0),true,"722") self.RearCouple = self:CreateCouple(Vector(-419.5-7.5+6,0,-77),Angle(0,180,0),false,"717") else self.FrontCouple = self:CreateCouple(Vector( 454 -8,0,-79),Angle(0,0,0),true,"722") self.RearCouple = self:CreateCouple(Vector(-419-6.8+8,0,-79),Angle(0,180,0),false,"717") end self.FrontBogey.DisableSound = 1 self.RearBogey.DisableSound = 1 self.FrontCouple.EKKDisconnected = true -- Initialize key mapping self.KeyMap = { [KEY_W] = "PanelKVUp", [KEY_S] = "PanelKVDown", [KEY_1] = "PanelKV1", [KEY_2] = "PanelKV2", [KEY_3] = "PanelKV2", [KEY_4] = "PanelKV4", [KEY_5] = "PanelKV5", [KEY_6] = "PanelKV6", [KEY_7] = "PanelKV7", [KEY_8] = "EmergencyDriveSet", [KEY_0] = "KRO+", [KEY_9] = "KRO-", [KEY_V] = "DoorCloseA", [KEY_A] = "DoorLeft", [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_1] = "SarmatF1Set", [KEY_PAD_2] = "SarmatF2Set", [KEY_PAD_3] = "SarmatF3Set", [KEY_PAD_4] = "SarmatF4Set", }, [KEY_F] = "PneumaticBrakeUp", [KEY_R] = "PneumaticBrakeDown", [KEY_PAD_1] = "PneumaticBrakeSet1", [KEY_PAD_2] = "PneumaticBrakeSet2", [KEY_PAD_3] = "PneumaticBrakeSet3", [KEY_PAD_4] = "PneumaticBrakeSet4", [KEY_PAD_5] = "PneumaticBrakeSet5", [KEY_PAD_6] = "PneumaticBrakeSet6", [KEY_PAD_MULTIPLY] = "EmergencyDriveSet", [KEY_L] = "HornEngage", } self.TrainWireInverts = { [8]=true } -- Cross connections in train wires self.TrainWireCrossConnections = { [4] = 3, -- Orientation F<->B [13] = 12, -- Reverser F<->B [38] = 37, -- Doors L<->R } self.InteractionZones = { { ID = "RearTrainLineIsolationToggle", Pos = Vector(-469.8, -34, -65), Radius = 8, }, { ID = "RearBrakeLineIsolationToggle", Pos = Vector(-469.8, 35, -65), Radius = 8, }, { ID = "RearDoor", Pos = Vector(-464.8, -38, 0), Radius = 20, }, { ID = "PassengerDoor", Pos = Vector(374, -7, 0), Radius = 13, }, { ID = "CabinDoorLeft", Pos = Vector(400, 62, -7), Radius = 20, }, { ID = "CabinDoorLeft", Pos = Vector(400, 62, -30), Radius = 20, }, { ID = "CabinDoorRight", Pos = Vector(400, -62, -7), Radius = 20, }, { ID = "CabinDoorRight", Pos = Vector(400, -62, -30), Radius = 20, }, } self.PassengerDoor = false self.CabinDoorLeft = false self.CabinDoorRight = false self.RearDoor = false self:SetNW2Float("UPONoiseVolume",math.Rand(0,0.3)) self:SetNW2Float("UPOVolume",math.Rand(0.8,1)) self.Scheme = 1 end function ENT:NonSupportTrigger() self.VAH:TriggerInput("Set",1) self.RCARS:TriggerInput("Set",0) self.K9:TriggerInput("Set",0) self.Plombs.VAH = nil self.Plombs.RCARS = nil self.Plombs.K9 = nil end function ENT:OnUPOArrived() return self.SarmatUPO:TriggerInput("CheckUPO") end -------------------------------------------------------------------------------- function ENT:Think() local retVal = self.BaseClass.Think(self) local power = self.BUKV.Power > 0 --[[ if self:GetWagonNumber() == 22010 or self:EntIndex()==1560 then --DEBUG local accel = 0 for i=1,#self.WagonList do accel=accel+self.WagonList[i].Acceleration end local drivers = {self.DriverSeat,self.InstructorsSeat,self.ExtraSeat1,self.ExtraSeat2} if math.abs(accel) > 0.1 then for k,v in pairs(drivers) do if IsValid(v) and IsValid(v:GetDriver()) then v:GetDriver():ChatPrint(Format("v=%.2f I=%.2f RK=%02d a=%.2f",self.Speed,0 or (self.Electric.I13+self.Electric.I24)/2,0 or self.RheostatController.SelectedPosition or 0,accel/#self.WagonList))--(accel/#self.WagonList))) end end end end self.TestA = self.TestA or nil self.TestV = self.TestV or nil local accel = self.Acceleration if (1 < self.Speed and self.Speed < 99) and self.Panel.TargetController < 0 and not self.TestA then self.TestA = CurTime() self.TestV = self.Speed/3600*1000 self.TestTyp = self.Speed > 55 and 2 or 1 self.TestS = 0 end if self.Panel.TargetController >= 0 and self.TestA then self.TestA = nil self.TestV = nil self.TestS = nil end if self.TestS then self.TestS=self.TestS+self.Speed*self.SpeedSign/3600*1000*self.DeltaTime end if (self.Speed<2 and self.TestTyp ==2 or self.Speed<2 and self.TestTyp ==1) and self.TestA then local curSpeed = self.Speed/3600*1000 local a = (curSpeed-self.TestV)/(CurTime()-self.TestA) RunConsoleCommand("say",Format("[%05d]V0= %.1f V1=%.1f t=%.2f a=%.2f s=%.1f",self:GetWagonNumber(),self.TestV*3600/1000,curSpeed*3600/1000,CurTime()-self.TestA,a,self.TestS)) self.TestA = nil self.TestV = nil self.TestS = nil end--]] --self:SetPackedRatio("async1", math.min(self.Speed/7,self.AsyncInverter.State*math.Clamp(1+(self.Speed-15)/120,1,2))) --self:SetPackedRatio("async1state", self.AsyncInverter.State) --self:SetPackedRatio("asyncfreq", self.AsyncInverter.InverterFrequency) --print() if self.AsyncInverter.State==1 then local state = math.abs(self.AsyncInverter.InverterFrequency/13)--(10+8*math.Clamp((self.AsyncInverter.State-0.4)/0.4,0,1))) self:SetPackedRatio("asynccurrent", math.Clamp(state*(state+self.AsyncInverter.State/1),0,1)) else local state = math.abs(self.AsyncInverter.InverterFrequency/(11+self.AsyncInverter.State*5))--(10+8*math.Clamp((self.AsyncInverter.State-0.4)/0.4,0,1))) self:SetPackedRatio("asynccurrent", math.Clamp(state*(state+self.AsyncInverter.State/1),0,1)) end self:SetPackedRatio("asyncstate", math.Clamp(self.AsyncInverter.State/0.2*math.abs(self.AsyncInverter.Current)/100,0,1)) self:SetPackedRatio("chopper", math.Clamp(self.Electric.Chopper>0 and self.Electric.Iexit/100 or 0,0,1)) --print(self.Electric.Chopper,self.Electric.Iexit/100) self:SetPackedBool("BattOnL",self.Panel.BattOn) self:SetPackedBool("BattOffL",self.Panel.BattOff) self:SetPackedBool("BattPressed",self.Electric.BatterySound>0) self:SetPackedRatio("ControllerPosition",self.Panel.Controller) self:SetPackedRatio("ReverserPosition",self.KRO.Value/2) self:SetPackedRatio("CompressorPosition",self.Compressor.Value) self:SetPackedRatio("PassVent",self.PassVent.Value/4) self:SetPackedRatio("VRU",self.VRU.Value/2) self:SetPackedRatio("BARSMode",self.BARSMode.Value/2) self:SetPackedRatio("PantSC",self.PantSC.Value/4) self:SetPackedRatio("GlassCleaner",self.GlassCleaner.Value/2) self:SetPackedRatio("Headlights",self.Headlights.Value/2) self:SetPackedRatio("DoorClose",self.DoorClose.Value/2) self:SetPackedRatio("CabinLight",self.CabinLight.Value/2) self:SetPackedBool("LampLPT",self.BUKP.LPT) self:SetPackedBool("LampRU",self.Panel.LRU > 0) self:SetPackedBool("LampAVS",self.Panel.AVS > 0) self:SetPackedBool("LampRC",self.Panel.RC > 0) self:SetPackedBool("LampSD",self.Electric.LSD > 0) self:SetPackedBool("RadioRVS",self.Panel.VPR1>0) self:SetPackedBool("RadioMotorola",self.Panel.VPR2>0) self:SetPackedBool("LampLRD",self.ALSCoil.F6 > 0) self:SetPackedBool("Lamp04",self.ALSCoil.NoFreq > 0) self:SetPackedBool("Lamp0",self.ALSCoil.F5 > 0) self:SetPackedBool("Lamp40",self.ALSCoil.F4 > 0) self:SetPackedBool("Lamp60",self.ALSCoil.F3 > 0) self:SetPackedBool("Lamp70",self.ALSCoil.F2 > 0) self:SetPackedBool("Lamp80",self.ALSCoil.F1 > 0) 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) self:SetPackedRatio("SalonLighting",math.min(1,self.Panel.MainLights+self.Panel.EmergencyLights*0.3)) self:SetPackedBool("CompressorWork",self.Pneumatic.Compressor) self:SetPackedBool("DoorLeftLamp",self.BUKP.DoorLeft) self:SetPackedBool("DoorRightLamp",self.BUKP.DoorRight) self:SetPackedBool("EmergencyBrakeTPlusL",self.Panel.EmergencyBrakeTPlusL > 0) self:SetPackedBool("EmergencyDriveL",self.Panel.EmergencyDriveL > 0) --self:SetPackedRatio("BatteryVoltage",(self.BUKV.Battery and (self.BUKV.PSN and 82 or 65) or 0)/150) self:SetPackedRatio("HighVoltage",self.TR.Main750V/1000) self:SetPackedRatio("LV",(self.Electric.Power*(65+15*self:ReadTrainWire(33)))/150) self:SetPackedRatio("CranePosition", self.Pneumatic.DriverValvePosition) self:SetPackedRatio("BLPressure", self.Pneumatic.BrakeLinePressure/16.0) self:SetPackedRatio("TLPressure", self.Pneumatic.TrainLinePressure/16.0) self:SetPackedRatio("BCPressure", math.min(3.2,self.Pneumatic.BrakeCylinderPressure)/6.0) self:SetPackedBool("SOSD",self.Panel.SOSD>0) self:SetPackedBool("SOSDLamp",self.BUKP.SOSD>0) self.SOSD = self.Panel.SOSD>0 self:SetPackedBool("BortPneumo",self.Panel.BrW>0) self:SetPackedBool("BortLSD",self.Panel.DoorsW>0) self:SetPackedBool("BortBV",self.Panel.GRP>0) 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) self:SetPackedBool("RearDoor",self.RearDoor) 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) if IsValid(self.FrontBogey) and IsValid(self.RearBogey) and not self.IgnoreEngine then local A = self.AsyncInverter.Torque self.FrontBogey.MotorForce = 43000+9000*(A < 0 and 1 or 0)--35300 self.FrontBogey.Reversed = self.Electric.Reverser < 0 self.FrontBogey.DisableSound = 1 self.FrontBogey.DisableContacts = self.Electric.DisablePant > 0 self.RearBogey.MotorForce = 43000+9000*(A < 0 and 1 or 0)--35300 self.RearBogey.Reversed = self.Electric.Reverser > 0 self.RearBogey.DisableSound = 1 self.RearBogey.DisableContacts = self.Electric.DisablePant > 0 -- These corrections are required to beat source engine friction at very low values of motor power local P = math.max(0,0.04449 + 1.06879*math.abs(A) - 0.465729*A^2) if math.abs(A) > 0.4 then P = math.abs(A) end if math.abs(A) < 0.05 then P = 0 end if self.Speed < 10 then P = P*(1.0 + 0.5*(10.0-self.Speed)/10.0) end self.RearBogey.MotorPower = P*0.5*((A > 0) and 1 or -1) self.FrontBogey.MotorPower = P*0.5*((A > 0) and 1 or -1) -- Apply brakes self.FrontBogey.PneumaticBrakeForce = 50000.0--3000 --40000 self.FrontBogey.BrakeCylinderPressure = self.Pneumatic.BrakeCylinderPressure self.FrontBogey.ParkingBrakePressure = math.max(0,(3-self.Pneumatic.ParkingBrakePressure)/3)/2 self.FrontBogey.BrakeCylinderPressure_dPdT = -self.Pneumatic.BrakeCylinderPressure_dPdT self.RearBogey.PneumaticBrakeForce = 50000.0--3000 --40000 self.RearBogey.BrakeCylinderPressure = self.Pneumatic.BrakeCylinderPressure self.RearBogey.BrakeCylinderPressure_dPdT = -self.Pneumatic.BrakeCylinderPressure_dPdT self.RearBogey.ParkingBrakePressure = math.max(0,(3-self.Pneumatic.ParkingBrakePressure)/3)/2 end return retVal end function ENT:OnCouple(train,isfront) if isfront and self.FrontAutoCouple then self.FrontBrakeLineIsolation:TriggerInput("Open",1.0) self.FrontTrainLineIsolation:TriggerInput("Open",1.0) self.FrontAutoCouple = false elseif not isfront and self.RearAutoCouple then self.RearBrakeLineIsolation:TriggerInput("Open",1.0) self.RearTrainLineIsolation:TriggerInput("Open",1.0) self.RearAutoCouple = false end self.BaseClass.OnCouple(self,train,isfront) end function ENT:OnButtonPress(button,ply) if string.find(button,"PneumaticBrakeSet") then self.Pneumatic:TriggerInput("BrakeSet",tonumber(button:sub(-1,-1))) return end if button == "PassengerDoor" then self.PassengerDoor = not self.PassengerDoor end if button == "CabinDoorLeft" then self.CabinDoorLeft = not self.CabinDoorLeft end if button == "CabinDoorRight" then self.CabinDoorRight = not self.CabinDoorRight end if button == "RearDoor" then self.RearDoor = not self.RearDoor end if button == "DoorLeft" then self.DoorSelect:TriggerInput("Set",0) self.DoorLeft1:TriggerInput("Set",1) end if button == "DoorRight" then self.DoorSelect:TriggerInput("Set",1) self.DoorRight:TriggerInput("Set",1) end if button == "DoorCloseA" then if self.DoorClose.Value == 1 then self.DoorClose:TriggerInput("Set",2) else self.DoorClose:TriggerInput("Set",1) end end if button == "DoorCloseM" then if self.DoorClose.Value == 1 then self.DoorClose:TriggerInput("Set",0) else self.DoorClose:TriggerInput("Set",1) end end end function ENT:OnButtonRelease(button,ply) if string.find(button,"PneumaticBrakeSet") then if button == "PneumaticBrakeSet1" and (self.Pneumatic.DriverValvePosition == 1) then self.Pneumatic:TriggerInput("BrakeSet",2) end return end if button == "DoorLeft" then self.DoorLeft1:TriggerInput("Set",0) end if button == "DoorRight" then self.DoorRight:TriggerInput("Set",0) end end