mirror of
https://github.com/metrostroi-repo/MetrostroiAddon.git
synced 2026-05-02 00:42:29 +00:00
538 lines
19 KiB
Lua
538 lines
19 KiB
Lua
AddCSLuaFile("cl_init.lua")
|
|
AddCSLuaFile("shared.lua")
|
|
include("shared.lua")
|
|
|
|
--------------------------------------------------------------------------------
|
|
function ENT:Initialize()
|
|
-- Defined train information
|
|
self.SubwayTrain = {
|
|
Type = "AI",
|
|
Name = "",
|
|
}
|
|
if not self.TrainType then self.TrainType = "81-717" end
|
|
-- Set model and initialize
|
|
self.NoPhysics = true
|
|
if self.TrainType == "81-717" then self:SetModel("models/metrostroi/81/81-7036.mdl") end
|
|
if self.TrainType == "81-714" then self:SetModel("models/metrostroi/81/81-7037.mdl") end
|
|
self.BaseClass.Initialize(self)
|
|
|
|
-- Create bogeys
|
|
self.FrontBogey = self:CreateBogey(Vector( 325-20,0,-75),Angle(0,180,0),true)
|
|
self.RearBogey = self:CreateBogey(Vector(-325-10,0,-75),Angle(0,0,0),false)
|
|
|
|
-- Seats
|
|
if self.TrainType == "81-717" then
|
|
self.DriverSeat = self:CreateSeat("driver",Vector(410,-2,-23))
|
|
--self.InstructorsSeat = self:CreateSeat("instructor",Vector(410,35,-28))
|
|
--self.ExtraSeat = self:CreateSeat("instructor",Vector(410,-35,-28))
|
|
end
|
|
--[[
|
|
for i=1,1 do --17
|
|
local pos = Vector(280-(i-1)*30-math.floor((i-1)/5)*80,-47,-32)
|
|
local p1 = self:CreateSeat("passenger",pos,Angle(0,90,0))
|
|
pos.y = -pos.y
|
|
local p2 = self:CreateSeat("passenger",pos,Angle(0,270,0))
|
|
end]]
|
|
|
|
-- Setup door positions
|
|
self.LeftDoorPositions = {}
|
|
self.RightDoorPositions = {}
|
|
for i=0,3 do
|
|
table.insert(self.LeftDoorPositions,Vector(353.0 - 35*0.5 - 231*i,65,-1.8))
|
|
table.insert(self.RightDoorPositions,Vector(353.0 - 35*0.5 - 231*i,-65,-1.8))
|
|
end
|
|
|
|
-- Find SOME sort of route
|
|
local route
|
|
for k,v in pairs(Metrostroi.AIConfiguration) do
|
|
if not route then route = k end
|
|
end
|
|
|
|
-- Initial setup
|
|
if not self.Route then self.Route = route end
|
|
if (not self.PathID) and (route) and Metrostroi.AIConfiguration[route] then
|
|
self.PathID = Metrostroi.AIConfiguration[route].Path
|
|
end
|
|
self.Position = self.Position or 100
|
|
self.Velocity = 0
|
|
self.RheostatPosition = 0
|
|
|
|
-- Lights
|
|
if self.TrainType == "81-717" then
|
|
self.Lights = {
|
|
-- Head
|
|
[1] = { "headlight", Vector(465,0,-20), Angle(0,0,0), Color(176,161,132), fov = 100 },
|
|
[2] = { "glow", Vector(460, 51,-23), Angle(0,0,0), Color(255,255,255), brightness = 2 },
|
|
[3] = { "glow", Vector(460,-51,-23), Angle(0,0,0), Color(255,255,255), brightness = 2 },
|
|
[4] = { "glow", Vector(460,-8, 55), Angle(0,0,0), Color(255,255,255), brightness = 0.3 },
|
|
[5] = { "glow", Vector(460,-8, 55), Angle(0,0,0), Color(255,255,255), brightness = 0.3 },
|
|
[6] = { "glow", Vector(460, 2, 55), Angle(0,0,0), Color(255,255,255), brightness = 0.3 },
|
|
[7] = { "glow", Vector(460, 2, 55), Angle(0,0,0), Color(255,255,255), brightness = 0.3 },
|
|
|
|
-- Reverse
|
|
[8] = { "light", Vector(458,-45, 55), Angle(0,0,0), Color(255,0,0), brightness = 10, scale = 1.0 },
|
|
[9] = { "light", Vector(458, 45, 55), Angle(0,0,0), Color(255,0,0), brightness = 10, scale = 1.0 },
|
|
|
|
-- Cabin
|
|
[10] = { "dynamiclight", Vector( 420, 0, 35), Angle(0,0,0), Color(255,255,255), brightness = 0.1, distance = 550 },
|
|
|
|
-- Interior
|
|
[12] = { "dynamiclight", Vector( 0, 0, 5), Angle(0,0,0), Color(255,255,255), brightness = 3, distance = 400 },
|
|
|
|
-- Side lights
|
|
[14] = { "light", Vector(-50, 68, 54), Angle(0,0,0), Color(255,0,0), brightness = 0.5, scale = 0.10, texture = "models/metrostroi_signals/signal_sprite_002.vmt" },
|
|
[15] = { "light", Vector(4, 68, 54), Angle(0,0,0), Color(150,255,255), brightness = 0.6, scale = 0.10, texture = "models/metrostroi_signals/signal_sprite_002.vmt" },
|
|
[16] = { "light", Vector(1, 68, 54), Angle(0,0,0), Color(0,255,0), brightness = 0.5, scale = 0.10, texture = "models/metrostroi_signals/signal_sprite_002.vmt" },
|
|
[17] = { "light", Vector(-2, 68, 54), Angle(0,0,0), Color(255,255,0), brightness = 0.5, scale = 0.10, texture = "models/metrostroi_signals/signal_sprite_002.vmt" },
|
|
|
|
[18] = { "light", Vector(-50, -69, 54), Angle(0,0,0), Color(255,0,0), brightness = 0.5, scale = 0.10, texture = "models/metrostroi_signals/signal_sprite_002.vmt" },
|
|
[19] = { "light", Vector(5, -69, 54), Angle(0,0,0), Color(150,255,255), brightness = 0.6, scale = 0.10, texture = "models/metrostroi_signals/signal_sprite_002.vmt" },
|
|
[20] = { "light", Vector(2, -69, 54), Angle(0,0,0), Color(0,255,0), brightness = 0.5, scale = 0.10, texture = "models/metrostroi_signals/signal_sprite_002.vmt" },
|
|
[21] = { "light", Vector(-1, -69, 54), Angle(0,0,0), Color(255,255,0), brightness = 0.5, scale = 0.10, texture = "models/metrostroi_signals/signal_sprite_002.vmt" },
|
|
}
|
|
end
|
|
if self.TrainType == "81-714" then
|
|
self.Lights = {
|
|
-- Interior
|
|
[12] = { "dynamiclight", Vector( 0, 0, 5), Angle(0,0,0), Color(255,255,255), brightness = 3, distance = 400 },
|
|
|
|
-- Side lights
|
|
[14] = { "light", Vector(-50, 68, 54), Angle(0,0,0), Color(255,0,0), brightness = 0.5, scale = 0.10, texture = "models/metrostroi_signals/signal_sprite_002.vmt" },
|
|
[15] = { "light", Vector(4, 68, 54), Angle(0,0,0), Color(150,255,255), brightness = 0.6, scale = 0.10, texture = "models/metrostroi_signals/signal_sprite_002.vmt" },
|
|
[16] = { "light", Vector(1, 68, 54), Angle(0,0,0), Color(0,255,0), brightness = 0.5, scale = 0.10, texture = "models/metrostroi_signals/signal_sprite_002.vmt" },
|
|
[17] = { "light", Vector(-2, 68, 54), Angle(0,0,0), Color(255,255,0), brightness = 0.5, scale = 0.10, texture = "models/metrostroi_signals/signal_sprite_002.vmt" },
|
|
|
|
[18] = { "light", Vector(-50, -69, 54), Angle(0,0,0), Color(255,0,0), brightness = 0.5, scale = 0.10, texture = "models/metrostroi_signals/signal_sprite_002.vmt" },
|
|
[19] = { "light", Vector(5, -69, 54), Angle(0,0,0), Color(150,255,255), brightness = 0.6, scale = 0.10, texture = "models/metrostroi_signals/signal_sprite_002.vmt" },
|
|
[20] = { "light", Vector(2, -69, 54), Angle(0,0,0), Color(0,255,0), brightness = 0.5, scale = 0.10, texture = "models/metrostroi_signals/signal_sprite_002.vmt" },
|
|
[21] = { "light", Vector(-1, -69, 54), Angle(0,0,0), Color(255,255,0), brightness = 0.5, scale = 0.10, texture = "models/metrostroi_signals/signal_sprite_002.vmt" },
|
|
}
|
|
end
|
|
|
|
-- Prop-protection related
|
|
if CPPI and IsValid(self.Owner) then
|
|
self:CPPISetOwner(self.Owner)
|
|
end
|
|
-- Spawn a dummy consist
|
|
if (self.TrainType == "81-717") and (not self.TrainHead) then
|
|
for i=2,5 do
|
|
local ent = ents.Create("gmod_subway_ai")
|
|
if i == 5
|
|
then ent.TrainType = "81-717"
|
|
else ent.TrainType = "81-714"
|
|
end
|
|
ent.TrainIndex = i
|
|
ent.TrainHead = self
|
|
ent.Owner = self.Owner
|
|
ent:Spawn()
|
|
table.insert(self.TrainEntities,ent)
|
|
end
|
|
end
|
|
--self:Remove()
|
|
-- Type
|
|
self:SetNW2String("TrainType",self.TrainType)
|
|
end
|
|
|
|
--[[concommand.Add("metrostroi_ai_spawn", function(ply, _, args)
|
|
if (ply:IsValid()) and (not ply:IsAdmin()) then return end
|
|
|
|
local pathid = tonumber(args[2]) or 1
|
|
local trainCounter = tonumber(args[1]) or 1
|
|
local prevEnt
|
|
timer.Create("metrostroi-ai-spawntimer-"..pathid,1.0,0,function()
|
|
if prevEnt then
|
|
if (pathid == 1) and (prevEnt.Position < 260) then
|
|
return
|
|
end
|
|
if (pathid == 2) and (prevEnt.Position < 960) then
|
|
return
|
|
end
|
|
end
|
|
if trainCounter < 1 then return end
|
|
|
|
local ent = ents.Create("gmod_subway_ai")
|
|
ent.Position = 150
|
|
ent.PathID = pathid
|
|
ent:Spawn()
|
|
prevEnt = ent
|
|
trainCounter = trainCounter - 1
|
|
print("Spawning AI trains (path "..pathid.."), left: "..trainCounter)
|
|
end)
|
|
end)
|
|
|
|
concommand.Add("metrostroi_ai_clear", function(ply, _, args)
|
|
if (ply:IsValid()) and (not ply:IsAdmin()) then return end
|
|
for k,v in pairs(ents.FindByClass("gmod_subway_ai")) do
|
|
SafeRemoveEntity(v)
|
|
if args[1] then print("Removed one") return end
|
|
end
|
|
--timer.Create("metrostroi-ai-spawntimer",1.0,0,function()end)
|
|
end)]]--
|
|
|
|
concommand.Add("metrostroi_ai_info", function(ply, _, args)
|
|
if (ply:IsValid()) and (not ply:IsAdmin()) then return end
|
|
for k,v in pairs(ents.FindByClass("gmod_subway_ai")) do
|
|
if not v.TrainHead then
|
|
print(Format("Train to [%03d][%02d] (%.0f m %.02f km/h, left %0.3f m)",
|
|
v.TargetStation or 0,v.TargetPlatform or 0,v.Position,v.Speed,
|
|
(v.PlatformEdgeX or 0) - v.Position))
|
|
end
|
|
end
|
|
end)
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Train driving AI
|
|
--------------------------------------------------------------------------------
|
|
function ENT:DoAI(dT)
|
|
-- Get a schedule
|
|
if self.Schedule and (#self.Schedule == 0) then
|
|
self.Schedule = nil
|
|
end
|
|
if (not self.Schedule) and (not self.NoStation) then
|
|
self.Schedule = Metrostroi.GenerateSchedule(self.Route)
|
|
self.StopTimer = 10
|
|
end
|
|
|
|
-- See if must move to next station
|
|
if self.Schedule then
|
|
if ((Metrostroi.ServerTime()+10000 > (self.Schedule[1][3]*60)) and (self.StopTimer < 0)) or
|
|
(self.StopTimer < -200) then
|
|
table.remove(self.Schedule,1)
|
|
self.StopTimer = 10
|
|
end
|
|
end
|
|
|
|
-- Get current target station info
|
|
local platformEdgeX
|
|
if self.Schedule and self.Schedule[1] then
|
|
local targetStation = self.Schedule[1][1]
|
|
local targetPlatform = self.Schedule[1][2]
|
|
local stationData = Metrostroi.Stations[targetStation]
|
|
local platformData
|
|
if stationData then platformData = stationData[targetPlatform] end
|
|
if platformData then
|
|
platformEdgeX = math.max(platformData.x_end,platformData.x_start)
|
|
end
|
|
if platformData and platformData.node_end then
|
|
if platformData.node_end.path.id ~= self.PathID then
|
|
--print("WRONG PATH")
|
|
platformEdgeX = nil
|
|
end
|
|
end
|
|
self.TargetStation = targetStation
|
|
self.TargetPlatform = targetPlatform
|
|
else
|
|
self.NoStation = true
|
|
end
|
|
self.PlatformEdgeX = platformEdgeX
|
|
|
|
if platformEdgeX then
|
|
if self.Position > platformEdgeX then
|
|
--print("Overrun!",self.Position,platformEdgeX)
|
|
table.remove(self.Schedule,1)
|
|
self.StopTimer = 10
|
|
end
|
|
end
|
|
|
|
-- Get current information on driving
|
|
local speedLimit = self.ALS_ARS.SpeedLimit
|
|
local nextLimit = self.ALS_ARS.NextLimit
|
|
local targetSpeed = nextLimit
|
|
--print()
|
|
if nextLimit == 0 then targetSpeed = speedLimit end
|
|
|
|
-- Move at slow speed to next red light or blocked section
|
|
if targetSpeed == 0 then targetSpeed = 20 end
|
|
-- If there is a red light ahead, stop once in its range
|
|
if self.RedLightDistance and (self.RedLightDistance < 20) then
|
|
targetSpeed = 0
|
|
end
|
|
|
|
-- Stop at station gradually
|
|
if platformEdgeX and (platformEdgeX > self.Position) then
|
|
local dX = platformEdgeX - self.Position
|
|
if dX < 100 then
|
|
targetSpeed = math.min(targetSpeed,55) * (math.max(0.0,math.min(1.0,(dX-12)/90))^0.5)
|
|
if dX > 18 then targetSpeed = math.max(targetSpeed,20) end
|
|
if self.Speed < 1 then
|
|
self.StopTimer = self.StopTimer - dT
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Wait for schedule start
|
|
if (self.PathID == 1) and (self.Position < 250) and
|
|
(self.Schedule) and (self.Schedule[1]) then
|
|
local dT = self.Schedule[1][3]*60 - Metrostroi.ServerTime()
|
|
--if dT > 90 then targetSpeed = 0 end
|
|
end
|
|
--targetSpeed = 0
|
|
-- Reached target speed, stop accelerating
|
|
if self.Speed > (targetSpeed-2) then
|
|
self.Accelerating = false
|
|
end
|
|
-- Speed is below required, try to accelerate
|
|
if self.Speed < (targetSpeed-10) then
|
|
self.Accelerating = true
|
|
end
|
|
-- Exceeding speed limit, apply brakes
|
|
if self.Speed > targetSpeed then
|
|
self.Braking = true
|
|
end
|
|
-- Braked enough, stop braking
|
|
if (self.Speed < (targetSpeed-5)) and (self.Braking) then
|
|
self.Braking = false
|
|
end
|
|
|
|
-- ARS system logic
|
|
if false and self.ALS_ARS.LVD then
|
|
self.Braking = true
|
|
self.Accelerating = false
|
|
end
|
|
--print(self.ALS_ARS.LVD)
|
|
if self.ALS_ARS.LVD
|
|
then self.ALS_ARS.AttentionPedal = true
|
|
else self.ALS_ARS.AttentionPedal = false
|
|
end
|
|
if speedLimit == 0 then self.ALS_ARS.AttentionPedal = true end
|
|
|
|
-- Apply pneumatic brakes if overspeeding much or stopped
|
|
self.Pneumo = false
|
|
if (self.Speed < 7) and (not self.Accelerating) then
|
|
self.Pneumo = true
|
|
end
|
|
if (self.Speed > (targetSpeed+5)) then
|
|
--self.Pneumo = true
|
|
end
|
|
|
|
-- Save for statistics
|
|
self.TargetSpeed = targetSpeed
|
|
--if self.RedLightDistance and (self.RedLightDistance < 30) then self.Pneumo = true end
|
|
end
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Train physics
|
|
--------------------------------------------------------------------------------
|
|
function ENT:DoPhysics(dT)
|
|
-- Slopes code
|
|
local slopeAngle = self:GetAngles().p
|
|
if slopeAngle > 180 then slopeAngle = slopeAngle-360 end
|
|
local slopeFactor = math.min(8.0,math.max(-8.0,slopeAngle))/8.0
|
|
|
|
-- Motor code
|
|
local motorPower = 0
|
|
if self.Accelerating then motorPower = 1.0 end
|
|
if self.Braking then motorPower = -1.0 end
|
|
|
|
local motorForce = 0
|
|
if motorPower > 0 then motorForce = 1.25*motorPower end
|
|
if motorPower < 0 then motorForce = -1.3*math.abs(motorPower) * math.max(-1.0,math.min(1.0,0.25*self.Velocity)) end
|
|
|
|
-- Brake code
|
|
local brakeForce = 0
|
|
if self.Pneumo then
|
|
brakeForce = -1.4*math.max(-1.0,math.min(1.0,3.0*self.Velocity))
|
|
slopeFactor = slopeFactor*math.max(-1.0,math.min(1.0,3.0*self.Velocity))
|
|
end
|
|
self.PneumoForce = brakeForce
|
|
|
|
-- Integrate position and velocity
|
|
self.Acceleration = 0
|
|
+motorForce
|
|
+brakeForce
|
|
-self.Velocity*0.0045
|
|
+slopeFactor*1.52
|
|
self.Velocity = self.Velocity + dT*self.Acceleration
|
|
self.Position = self.Position + dT*self.Velocity
|
|
--print(Format("%.2f/%.2f km/h %.0f m A-%s B-%s P-%s",
|
|
--self.Speed,self.TargetSpeed,self.Position,
|
|
--tostring(self.Accelerating),tostring(self.Braking),tostring(self.Pneumo)))
|
|
|
|
-- Info
|
|
self.MotorPower = motorPower
|
|
end
|
|
|
|
function ENT:Think()
|
|
-- Basic think loop
|
|
self.PrevTime = self.PrevTime or CurTime()
|
|
self.DeltaTime = (CurTime() - self.PrevTime)
|
|
self.PrevTime = CurTime()
|
|
|
|
--self:RecvPackedData()
|
|
self:NextThink(CurTime()+0.10)
|
|
|
|
-- Simulate equipment specific to trains
|
|
local dT = self.DeltaTime
|
|
if (self.TrainType == "81-717") and (not self.TrainHead) then
|
|
self.ALS_ARS:Think(dT,1)
|
|
end
|
|
|
|
-- Select path
|
|
if (not self.PathID) or (not self.Route) then return true end
|
|
local path = Metrostroi.Paths[self.PathID]
|
|
local config = Metrostroi.AIConfiguration[self.Route]
|
|
if self.Position > config.EndPosition then
|
|
self.Route = config.NextRoute
|
|
config = Metrostroi.AIConfiguration[self.Route]
|
|
self.PathID = config.Path
|
|
self.Position = config.SpawnPosition
|
|
self.Velocity = 0
|
|
|
|
self.Schedule = nil
|
|
self.NoStation = false
|
|
end
|
|
--self.Velocity = 0
|
|
|
|
----------------------------------------------------------------------------
|
|
-- If needed, update train physics and AI
|
|
if not self.TrainHead then
|
|
self:DoAI(dT)
|
|
self:DoPhysics(dT)
|
|
else
|
|
if not IsValid(self.TrainHead) then
|
|
SafeRemoveEntity(self)
|
|
return
|
|
end
|
|
|
|
self.Route = self.TrainHead.Route
|
|
self.PathID = self.TrainHead.PathID
|
|
self.Position = self.TrainHead.Position - 18.6*(self.TrainIndex-1)
|
|
self.Velocity = self.TrainHead.Velocity
|
|
self.MotorPower = self.TrainHead.MotorPower
|
|
self.PneumoForce = self.TrainHead.PneumoForce
|
|
end
|
|
|
|
|
|
----------------------------------------------------------------------------
|
|
-- Lighting
|
|
if self.TrainType == "81-717" then
|
|
self:SetLightPower(1, self.TrainHead == nil)
|
|
self:SetLightPower(2, self.TrainHead == nil)
|
|
self:SetLightPower(3, self.TrainHead == nil)
|
|
self:SetLightPower(4, self.TrainHead == nil)
|
|
self:SetLightPower(5, self.TrainHead == nil)
|
|
self:SetLightPower(6, self.TrainHead == nil)
|
|
self:SetLightPower(7, self.TrainHead == nil)
|
|
self:SetLightPower(8, self.TrainHead ~= nil)
|
|
self:SetLightPower(9, self.TrainHead ~= nil)
|
|
self:SetLightPower(10, (CurTime() % 60) > 0.1)
|
|
self:SetLightPower(12, (CurTime() % 60) > 0.1)
|
|
end
|
|
if self.TrainType == "81-714" then
|
|
self:SetLightPower(12, (CurTime() % 60) > 0.1)
|
|
end
|
|
-- Pneumatic brakes
|
|
self.PneumaticPressure = self.PneumaticPressure or 0
|
|
self.PneumaticPressure_dPdT = self.PneumaticPressure_dPdT or 0
|
|
if self.Pneumo
|
|
then self.PneumaticPressure_dPdT = 0.65*(1.5 - self.PneumaticPressure)
|
|
else self.PneumaticPressure_dPdT = 0.65*(0.0 - self.PneumaticPressure)
|
|
end
|
|
self.PneumaticPressure = self.PneumaticPressure + self.PneumaticPressure_dPdT*dT
|
|
|
|
-- Minor state
|
|
if self.TrainHead then
|
|
self.LeftDoorsOpen = self.TrainHead.LeftDoorsOpen
|
|
self.RightDoorsOpen = self.TrainHead.RightDoorsOpen
|
|
else
|
|
self.LeftDoorsOpen = self.StopTimer and (self.StopTimer < 9)
|
|
self.RightDoorsOpen = self.StopTimer and (self.StopTimer < 9)
|
|
end
|
|
if self.LeftDoorsOpen ~= self.PrevLeftDoorsOpen then
|
|
self.PrevLeftDoorsOpen = self.LeftDoorsOpen
|
|
if self.LeftDoorsOpen then
|
|
self:PlayOnce("door_open1")
|
|
else
|
|
self:PlayOnce("door_close1")
|
|
end
|
|
end
|
|
if self.RightDoorsOpen ~= self.PrevRightDoorsOpen then
|
|
self.PrevRightDoorsOpen = self.RightDoorsOpen
|
|
if self.RightDoorsOpen then
|
|
self:PlayOnce("door_open1")
|
|
else
|
|
self:PlayOnce("door_close1")
|
|
end
|
|
end
|
|
self:SetPackedBool(21,self.LeftDoorsOpen)
|
|
self:SetPackedBool(22,self.LeftDoorsOpen)
|
|
self:SetPackedBool(23,self.LeftDoorsOpen)
|
|
self:SetPackedBool(24,self.LeftDoorsOpen)
|
|
self:SetPackedBool(25,self.RightDoorsOpen)
|
|
self:SetPackedBool(26,self.RightDoorsOpen)
|
|
self:SetPackedBool(27,self.RightDoorsOpen)
|
|
self:SetPackedBool(28,self.RightDoorsOpen)
|
|
self:SetPackedBool(52,1)
|
|
self:SetPackedBool(39,self.ALS_ARS.LVD and (not self.TrainHead))
|
|
|
|
-- Update state of all objects and sounds
|
|
self.Speed = math.abs(self.Velocity/0.277778)
|
|
self.FrontBogey.Speed = self.Speed
|
|
self.RearBogey.Speed = self.Speed
|
|
self.FrontBogey.MotorPower = self.MotorPower
|
|
self.RearBogey.MotorPower = self.MotorPower
|
|
self.FrontBogey.BrakeCylinderPressure_dPdT = -self.PneumaticPressure_dPdT
|
|
self.RearBogey.BrakeCylinderPressure_dPdT = -self.PneumaticPressure_dPdT
|
|
self.FrontBogey.BrakeSqueal = math.min(1,(3*math.abs(self.PneumoForce or 0))^1)
|
|
self.RearBogey.BrakeSqueal = math.min(1,(3*math.abs(self.PneumoForce or 0))^1)
|
|
|
|
|
|
----------------------------------------------------------------------------
|
|
-- Update train position
|
|
local vec,dir,node = Metrostroi.GetTrackPosition(path,self.Position)
|
|
if vec then
|
|
--local vec1,dir1 = Metrostroi.GetTrackPosition(path,self.Position+0)
|
|
local vec2,dir2 = Metrostroi.GetTrackPosition(path,self.Position-5)
|
|
if dir2 then
|
|
dir = dir2
|
|
end
|
|
|
|
if self.TrainHead then dir = -dir end
|
|
--[[local trace = {
|
|
start = vec,
|
|
endpos = vec + Vector(0,0,-384),
|
|
mask = MASK_NPCWORLDSTATIC
|
|
}
|
|
local result = util.TraceLine(trace)]]--
|
|
local rollAngle = Angle(0,0,0)--Angle(0,0,(180.0/math.pi)*math.acos(result.HitNormal.z))
|
|
|
|
self:SetPos(vec)
|
|
self:SetAngles(dir:Angle() + rollAngle)
|
|
end
|
|
|
|
-- Update information about restrictions in driving
|
|
self.RestrictionTimeout = self.RestrictionTimeout or 0
|
|
if (CurTime() - self.RestrictionTimeout) > 0.50 then
|
|
self.RestrictionTimeout = CurTime()
|
|
if node and (not self.TrainHead) then
|
|
self.RedLightDistance = nil
|
|
|
|
-- Check ARS signal/traffic light being red
|
|
local nextARS = Metrostroi.GetARSJoint(node,self.Position,true)
|
|
if nextARS and nextARS.AutoEnabled then
|
|
local arsOffset = (nextARS.ARSOffset or self.Position)
|
|
local dX = math.abs(arsOffset - self.Position)
|
|
if (not self.PlatformEdgeX) or (arsOffset < self.PlatformEdgeX) then
|
|
self.RedLightDistance = dX
|
|
end
|
|
end
|
|
|
|
-- Find other trains on the same line
|
|
if not self.RedLightDistance then
|
|
for k,v in pairs(ents.FindByClass("gmod_subway_ai")) do
|
|
if (v.PathID == self.PathID) and (v ~= self) and (v.Position > self.Position) then
|
|
self.RedLightDistance = math.abs(v.Position - self.Position)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- self:SendPackedData()
|
|
return true
|
|
end |