mirror of
https://github.com/metrostroi-repo/MetrostroiAddon.git
synced 2026-05-02 00:42:29 +00:00
677 lines
36 KiB
Lua
677 lines
36 KiB
Lua
include("shared.lua")
|
|
|
|
--------------------------------------------------------------------------------
|
|
function ENT:Initialize()
|
|
self.Sig = ""
|
|
self.OldName = ""
|
|
self.Models = {{},{},{}}
|
|
self.Signals = {}
|
|
self.Anims = {}
|
|
end
|
|
|
|
function ENT:Animate(clientProp, value, min, max, speed, damping, stickyness)
|
|
local id = clientProp
|
|
if not self.Anims[id] then
|
|
self.Anims[id] = {}
|
|
self.Anims[id].val = value
|
|
self.Anims[id].V = 0.0
|
|
end
|
|
|
|
if damping == false then
|
|
local dX = speed * self.DeltaTime
|
|
if value > self.Anims[id].val then
|
|
self.Anims[id].val = self.Anims[id].val + dX
|
|
end
|
|
if value < self.Anims[id].val then
|
|
self.Anims[id].val = self.Anims[id].val - dX
|
|
end
|
|
if math.abs(value - self.Anims[id].val) < dX then
|
|
self.Anims[id].val = value
|
|
end
|
|
else
|
|
-- Prepare speed limiting
|
|
local delta = math.abs(value - self.Anims[id].val)
|
|
local max_speed = 1.5*delta / self.DeltaTime
|
|
local max_accel = 0.5 / self.DeltaTime
|
|
|
|
-- Simulate
|
|
local dX2dT = (speed or 128)*(value - self.Anims[id].val) - self.Anims[id].V * (damping or 8.0)
|
|
if dX2dT > max_accel then dX2dT = max_accel end
|
|
if dX2dT < -max_accel then dX2dT = -max_accel end
|
|
|
|
self.Anims[id].V = self.Anims[id].V + dX2dT * self.DeltaTime
|
|
if self.Anims[id].V > max_speed then self.Anims[id].V = max_speed end
|
|
if self.Anims[id].V < -max_speed then self.Anims[id].V = -max_speed end
|
|
|
|
self.Anims[id].val = math.max(0,math.min(1,self.Anims[id].val + self.Anims[id].V * self.DeltaTime))
|
|
|
|
-- Check if value got stuck
|
|
if (math.abs(dX2dT) < 0.001) and stickyness and (self.DeltaTime > 0) then
|
|
self.Anims[id].stuck = true
|
|
end
|
|
end
|
|
return min + (max-min)*self.Anims[id].val
|
|
end
|
|
--------------------------
|
|
-- MAIN SPAWN FUNCTIONS --
|
|
--------------------------
|
|
function ENT:SpawnMainModels(pos,ang,LenseNum,add)
|
|
local TLM = self.TrafficLightModels[self.LightType]
|
|
for k,v in pairs(TLM) do
|
|
if type(v) == "string" and not k:find("long") then
|
|
if IsValid(self.Models[1][add and v..add or v]) then break else
|
|
if TLM[k.."_long"] and LenseNum >= 7 then
|
|
self.Models[1][add and v..add or v] = ClientsideModel(TLM[k.."_long"],RENDERGROUP_OPAQUE)
|
|
self.LongOffset = Vector(0,0,TLM[k.."_long_pos"])
|
|
else
|
|
self.Models[1][add and v..add or v] = ClientsideModel(v,RENDERGROUP_OPAQUE)
|
|
end
|
|
self.Models[1][add and v..add or v]:SetPos(self:LocalToWorld(pos))
|
|
self.Models[1][add and v..add or v]:SetAngles(self:LocalToWorldAngles(ang))
|
|
self.Models[1][add and v..add or v]:SetParent(self)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function ENT:SpawnHeads(ID,model,pos,ang,glass,notM,add)
|
|
if not IsValid(self.Models[1][ID]) then
|
|
self.Models[1][ID] = ClientsideModel(model,RENDERGROUP_OPAQUE)
|
|
self.Models[1][ID]:SetPos(self:LocalToWorld(pos))
|
|
self.Models[1][ID]:SetAngles(self:LocalToWorldAngles(ang))
|
|
self.Models[1][ID]:SetParent(self)
|
|
end
|
|
if self.RN and self.RN == self.RouteNumbers.sep then
|
|
self.RN = self.RN + 1
|
|
end
|
|
local id = self.RN
|
|
if id and not IsValid(self.Models[1]["rou"..id]) then
|
|
local rnadd = ((self.RouteNumbers[id] and self.RouteNumbers[id][1] ~= "X") and (self.RouteNumbers[id][3] and not self.RouteNumbers[id][2] and "2" or "") or "5")
|
|
self.Models[1]["rou"..id] = ClientsideModel("models/metrostroi/signals/mus/light_lampindicator"..rnadd..".mdl",RENDERGROUP_OPAQUE)
|
|
self.Models[1]["rou"..id]:SetPos(self:LocalToWorld(pos-self.RouteNumberOffset*Vector(self.Left and 0.2 or 1)))
|
|
self.Models[1]["rou"..id]:SetAngles(self:GetAngles())
|
|
self.Models[1]["rou"..id]:SetParent(self)
|
|
if self.RouteNumbers[id] then self.RouteNumbers[id].pos = pos-self.RouteNumberOffset*Vector(self.Left and 0.2 or 1) end
|
|
self.RN = self.RN + 1
|
|
end
|
|
if notM then
|
|
if glass then
|
|
for i,tbl in pairs(glass) do
|
|
if not IsValid(self.Models[1][tostring(ID).."_glass"..i]) then --NEWLENSES
|
|
self.Models[1][tostring(ID).."_glass"..i] = ClientsideModel(tbl[1],RENDERGROUP_OPAQUE)
|
|
self.Models[1][tostring(ID).."_glass"..i]:SetPos(self:LocalToWorld(pos+tbl[2]*Vector(add and -1 or 1,1,1)))
|
|
self.Models[1][tostring(ID).."_glass"..i]:SetAngles(self:LocalToWorldAngles(ang))
|
|
self.Models[1][tostring(ID).."_glass"..i]:SetParent(self)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function ENT:SetLight(ID,ID2,pos,ang,skin,State,Change)
|
|
if State >0 and Change and not IsValid(self.Models[3][ID..ID2]) then
|
|
self.Models[3][ID..ID2] = ClientsideModel("models/metrostroi/signals/mus/lamp_base.mdl",RENDERGROUP_OPAQUE)
|
|
self.Models[3][ID..ID2]:SetPos(self:LocalToWorld(pos))
|
|
self.Models[3][ID..ID2]:SetAngles(self:LocalToWorldAngles(ang))
|
|
self.Models[3][ID..ID2]:SetSkin(skin)
|
|
self.Models[3][ID..ID2]:SetParent(self)
|
|
self.Models[3][ID..ID2]:SetRenderMode(RENDERMODE_TRANSCOLOR)
|
|
self.Models[3][ID..ID2]:SetColor(Color(255,255,255,0))
|
|
end
|
|
if IsValid(self.Models[3][ID..ID2]) then
|
|
if State > 0 and Change then
|
|
self.Models[3][ID..ID2]:SetColor(Color(255,255,255,State*255))
|
|
elseif State == 0 then
|
|
self.Models[3][ID..ID2]:Remove()
|
|
end
|
|
end
|
|
end
|
|
|
|
function ENT:SpawnLetter(i,model,pos,letter,double)
|
|
if double ~= false and not IsValid(self.Models[2][i]) and (self.Double or not self.Left) and (not letter:match("s[1-3]") or letter == "s3" or self.Double and self.Left) then
|
|
self.Models[2][i] = ClientsideModel(model,RENDERGROUP_OPAQUE)
|
|
self.Models[2][i]:SetAngles(self:LocalToWorldAngles(Angle(0,180,0)))
|
|
self.Models[2][i]:SetPos(self:LocalToWorld(self.BasePosition+pos))
|
|
self.Models[2][i]:SetParent(self)
|
|
for k,v in pairs(self.Models[2][i]:GetMaterials()) do
|
|
if v:find("models/metrostroi/signals/let/let_start") then
|
|
self.Models[2][i]:SetSubMaterial(k-1,"models/metrostroi/signals/let/"..letter)
|
|
end
|
|
end
|
|
end
|
|
if not double and not IsValid(self.Models[2][i.."d"]) and (self.Double or self.Left) and (not letter:match("s[1-3]") or letter == "s3" or self.Double and not self.Left) then
|
|
self.Models[2][i.."d"] = ClientsideModel(model,RENDERGROUP_OPAQUE)
|
|
self.Models[2][i.."d"]:SetAngles(self:LocalToWorldAngles(Angle(0,180,0)))
|
|
self.Models[2][i.."d"]:SetPos(self:LocalToWorld((self.BasePosition+pos)*Vector(-1,1,1)))
|
|
self.Models[2][i.."d"]:SetParent(self)
|
|
for k,v in pairs(self.Models[2][i.."d"]:GetMaterials()) do
|
|
if v:find("models/metrostroi/signals/let/let_start") then
|
|
self.Models[2][i.."d"]:SetSubMaterial(k-1,"models/metrostroi/signals/let/"..letter)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function ENT:OnRemove()
|
|
self:RemoveModels()
|
|
end
|
|
|
|
function ENT:RemoveModels(final)
|
|
if self.Models and self.Models.have then
|
|
for _,v in pairs(self.Models) do if type(v) == "table" then for _,v1 in pairs(v) do v1:Remove() end end end
|
|
end
|
|
self.Models = {{},{},{}}
|
|
self.ModelsCreated = false
|
|
end
|
|
|
|
net.Receive("metrostroi-signal", function()
|
|
local ent = net.ReadEntity()
|
|
if not IsValid(ent) then return end
|
|
ent.LightType = net.ReadInt(3)
|
|
ent.Name = net.ReadString()
|
|
--ent.Name = " BUDAPEiT"..string.gsub(ent.Name,"[A-Za-z]*","")
|
|
ent.Lenses = net.ReadString()
|
|
ent.ARSOnly = ent.Lenses == "ARSOnly"
|
|
ent.RouteNumberSetup = net.ReadString()
|
|
ent.Left = net.ReadBool()
|
|
ent.Double = net.ReadBool()
|
|
ent.DoubleL = net.ReadBool()
|
|
ent.AutostopPresent = net.ReadBool()
|
|
if not ent.ARSOnly then
|
|
ent.LensesTBL = string.Explode("-",ent.Lenses)
|
|
end
|
|
if ent.RemoveModels then ent:RemoveModels() end
|
|
end)
|
|
|
|
function ENT:Think()
|
|
self.PrevTime = self.PrevTime or RealTime()
|
|
self.DeltaTime = (RealTime() - self.PrevTime)
|
|
self.PrevTime = RealTime()
|
|
if self:IsDormant() or Metrostroi and Metrostroi.ReloadClientside then
|
|
if not self.ReloadModels and self.ModelsCreated then
|
|
self:RemoveModels()
|
|
end
|
|
return
|
|
end
|
|
|
|
if self.ReloadModels then
|
|
self.ReloadModels = false
|
|
self:RemoveModels()
|
|
end
|
|
|
|
if not self.Name then
|
|
if self.sended and (CurTime() - self.sended) > 0 then
|
|
self.sended = nil
|
|
end
|
|
if not self.sended then
|
|
net.Start("metrostroi-signal")
|
|
net.WriteEntity(self)
|
|
net.SendToServer()
|
|
self.sended = CurTime() + 1.5
|
|
end
|
|
return
|
|
end
|
|
local TLM = self.TrafficLightModels[self.LightType]
|
|
|
|
if not self.ModelsCreated then
|
|
local ID = 0
|
|
local ID2 = 0
|
|
-- Create new clientside models
|
|
if not self.ARSOnly then
|
|
--SPAWN A OLD ROUTE Numbers
|
|
local rn1 = {}
|
|
local rn2 = {}
|
|
self.RouteNumbers = {}
|
|
self.SpecRouteNumbers = {}
|
|
for i=1,#self.RouteNumberSetup do
|
|
local CurRN = self.RouteNumberSetup[i]
|
|
if self.OldRouteNumberSetup[1]:find(CurRN) then
|
|
table.insert(rn1,CurRN)
|
|
elseif self.OldRouteNumberSetup[2]:find(CurRN) then
|
|
table.insert(rn2,CurRN)
|
|
elseif self.OldRouteNumberSetup[3]:find(CurRN) then
|
|
table.insert(self.SpecRouteNumbers,{CurRN,CurRN == "F"})
|
|
end
|
|
end
|
|
for i=1,#rn1,2 do
|
|
table.insert(self.RouteNumbers,{rn1[i],rn1[i+1],true})
|
|
end
|
|
for k,v in pairs(rn2) do
|
|
table.insert(self.RouteNumbers,{v})
|
|
end
|
|
self.Arrow = nil
|
|
if #self.SpecRouteNumbers > 0 then
|
|
for k,v in pairs(self.SpecRouteNumbers) do
|
|
if not v[2] then
|
|
self.Arrow = k
|
|
self.SpecRouteNumbers = v
|
|
break
|
|
end
|
|
end
|
|
end
|
|
local LenseNum = self.Arrow and 1 or 0
|
|
local OneLense = self.Arrow == nil
|
|
for k,v in ipairs(self.LensesTBL) do
|
|
if k > 1 and v:find("[RGBWYM]+") then
|
|
OneLense = false
|
|
end
|
|
for i=1,#v do
|
|
if v[i]:find("[RGBWYM]") then
|
|
LenseNum = LenseNum+1
|
|
end
|
|
end
|
|
end
|
|
if LenseNum == 0 then OneLense = false end
|
|
local offset = self.RenderOffset[self.LightType] or Vector(0,0,0)
|
|
self.LongOffset = self.LongOffset or Vector(0,0,0)
|
|
if not self.Left or self.Double then self:SpawnMainModels(self.BasePosition,Angle(0,0,0),LenseNum) end
|
|
if self.Left or self.Double then self:SpawnMainModels(self.BasePosition*Vector(-1,1,1),Angle(0,180,0),LenseNum,self.Double and "d" or nil) end
|
|
|
|
|
|
if not self.RouteNumbers.sep and #self.RouteNumbers > 1 then
|
|
self.RouteNumbers.sep = 2
|
|
elseif not self.RouteNumbers.sep and #self.RouteNumbers > 0 then
|
|
self.RouteNumbers.sep = 1
|
|
end
|
|
if self.RouteNumbers.sep and self.RouteNumbers[self.RouteNumbers.sep][1] ~= "X" then
|
|
local id = self.RouteNumbers.sep
|
|
local rnadd = self.RouteNumbers[id][3] and not self.RouteNumbers[id][2] and "3" or "4"
|
|
self.Models[1]["rous"] = ClientsideModel("models/metrostroi/signals/mus/light_lampindicator"..rnadd..".mdl",RENDERGROUP_OPAQUE)
|
|
self.RouteNumbers[id].pos = (self.BasePosition+offset+self.LongOffset-Vector(8,0,0))
|
|
if self.Left then self.RouteNumbers[id].pos = self.RouteNumbers[id].pos*Vector(-0.9,1,1) end
|
|
self.Models[1]["rous"]:SetPos(self:LocalToWorld(self.RouteNumbers[id].pos))
|
|
self.Models[1]["rous"]:SetAngles(self:GetAngles())
|
|
self.Models[1]["rous"]:SetParent(self)
|
|
end
|
|
if #self.RouteNumbers > 0 and (#self.RouteNumbers ~= 1 or not self.RouteNumbers.sep) then
|
|
self.RN = 1
|
|
self.RouteNumberOffset = Vector(10,0,0)
|
|
offset = offset + self.RouteNumberOffset*Vector(self.Left and -1 or 1,1,1)
|
|
else
|
|
self.RouteNumberOffset = nil
|
|
self.RN = nil
|
|
end
|
|
if self.AutostopPresent then
|
|
if not IsValid(self.Models[1]["autostop"]) then
|
|
self.Models[1]["autostop"] = ClientsideModel(self.AutostopModel[1],RENDERGROUP_OPAQUE)
|
|
self.Models[1]["autostop"]:SetPos(self:LocalToWorld(self.BasePosition+self.AutostopModel[2]))
|
|
self.Models[1]["autostop"]:SetAngles(self:GetAngles())
|
|
self.Models[1]["autostop"]:SetParent(self)
|
|
end
|
|
end
|
|
self.NamesOffset = Vector(0,0,0)
|
|
-- Create traffic light models
|
|
--if self.LightType > 2 then self.LightType = 2 end
|
|
--if self.LightType < 0 then self.LightType = 0 end
|
|
local first = true
|
|
for _,v in ipairs(self.LensesTBL) do
|
|
local data
|
|
if not self.TrafficLightModels[self.LightType][v] then
|
|
data = self.TrafficLightModels[self.LightType][#v-1]
|
|
else
|
|
if v == "M" then
|
|
self.RouteNumber = ID
|
|
end
|
|
data = self.TrafficLightModels[self.LightType][v]
|
|
end
|
|
if not data then continue end
|
|
if first then
|
|
first = false
|
|
else
|
|
offset = offset - Vector(0,0,data[1])
|
|
end
|
|
|
|
self.NamesOffset = self.NamesOffset + Vector(0,0,data[1])
|
|
if not self.Left or self.Double then self:SpawnHeads(ID,data[2],self.BasePosition + offset + self.LongOffset,Angle(0,0,0),data[3] and data[3].glass,v~="M") end
|
|
if self.Left or self.Double then self:SpawnHeads((self.Double and ID.."d" or ID),(not TLM.noleft) and data[2]:Replace(".mdl","_mirror.mdl") or data[2],self.BasePosition*Vector(-1,1,1) + offset + self.LongOffset,Angle(0,0,0),data[3] and data[3].glass,v~="M",true) end
|
|
if v ~= "M" then
|
|
for i = 1,#v do
|
|
ID2 = ID2 + 1
|
|
if not self.Signals[ID2] then self.Signals[ID2] = {} end
|
|
if not self.DoubleL then
|
|
self:SetLight(ID,ID2,self.BasePosition*Vector(self.Left and -1 or 1,1,1) + offset + self.LongOffset + data[3][i-1]*Vector(self.Left and -1 or 1,1,1),Angle(0,0,0),self.SignalConverter[v[i]]-1,0 )
|
|
else
|
|
self:SetLight(ID,ID2,self.BasePosition*Vector( 1,1,1) + offset + self.LongOffset + data[3][i-1]*Vector(1,1,1),Angle(0,0,0),self.SignalConverter[v[i]]-1,0)
|
|
self:SetLight(ID,ID2.."x",self.BasePosition*Vector(-1,1,1) + offset + self.LongOffset + data[3][i-1]*Vector(-1,1,1),Angle(0,0,0),self.SignalConverter[v[i]]-1,0)
|
|
end
|
|
end
|
|
end
|
|
|
|
ID = ID + 1
|
|
end
|
|
if self.Arrow then
|
|
local id = self.Arrow
|
|
self.Models[1]["roua"] = ClientsideModel("models/metrostroi/signals/mus/light_lampindicator4.mdl",RENDERGROUP_OPAQUE)
|
|
self.SpecRouteNumbers.pos = (self.BasePosition+offset+self.LongOffset-Vector(3,0,3))*Vector(self.Left and -1 or 1,1,self.Left and 0.85 or 1)-(self.RouteNumberOffset or Vector())
|
|
self.Models[1]["roua"]:SetPos(self:LocalToWorld(self.SpecRouteNumbers.pos))
|
|
self.Models[1]["roua"]:SetAngles(self:LocalToWorldAngles(Angle(self.Left and -90 or 90,0,0)))
|
|
self.Models[1]["roua"]:SetParent(self)
|
|
end
|
|
offset = self.RenderOffset[self.LightType]+(OneLense and TLM.name_one or TLM.name)+(OneLense and self.RouteNumberOffset or Vector())
|
|
if self.LightType == 1 then
|
|
offset = offset - self.NamesOffset
|
|
end
|
|
local double = self.LightType ~= 1 and string.find(self.Name,"^[A-Z][A-Z]")
|
|
if double then
|
|
if not self.Left or self.Double then
|
|
self:SpawnLetter(0,"models/metrostroi/signals/mus/sign_letter_small.mdl",offset - Vector(-1.5,0,0),(Metrostroi.LiterWarper[self.Name[0+1]] or self.Name[0+1]),true)
|
|
self:SpawnLetter(1,"models/metrostroi/signals/mus/sign_letter_small.mdl",offset - Vector(1.5,0,0),(Metrostroi.LiterWarper[self.Name[1+1]] or self.Name[1+1]),true)
|
|
end
|
|
if self.Left or self.Double then
|
|
self:SpawnLetter(0,"models/metrostroi/signals/mus/sign_letter_small.mdl",offset - Vector(1.5,0,0),(Metrostroi.LiterWarper[self.Name[0+1]] or self.Name[0+1]),false)
|
|
self:SpawnLetter(1,"models/metrostroi/signals/mus/sign_letter_small.mdl",offset - Vector(-1.5,0,0),(Metrostroi.LiterWarper[self.Name[1+1]] or self.Name[1+1]),false)
|
|
end
|
|
end
|
|
local min = 0
|
|
for i = double and 2 or 0,#self.Name-1 do
|
|
local id = (double and i-1 or i) - min
|
|
if double and i == 2 then offset = offset + Vector(0,0,1.62) end
|
|
if self.Name[i+1] == " " then continue end
|
|
if self.Name[i+1] == "/" then min = min + 1; continue end
|
|
--if not IsValid(self.Models[2][i]) then
|
|
self:SpawnLetter(i,"models/metrostroi/signals/mus/sign_letter.mdl",offset - Vector(0,0,id*5.85),(Metrostroi.LiterWarper[self.Name[i+1]] or self.Name[i+1]))
|
|
--end
|
|
end
|
|
if self.Name and self.Name:match("(/+)$") then
|
|
local i = #self.Name
|
|
local id = (double and i-1 or i) - min
|
|
self:SpawnLetter(i,"models/metrostroi/signals/mus/sign_letter.mdl",offset - Vector(0,0,id*5.85),Format("s%d",math.min(3,#self.Name:match("(/+)$"))))
|
|
end
|
|
else
|
|
local k = "m1"
|
|
|
|
if not IsValid(self.Models[1][k]) then
|
|
local v = TLM["m1"]
|
|
self.Models[1][k] = ClientsideModel(v,RENDERGROUP_OPAQUE)
|
|
self.Models[1][k]:SetPos(self:LocalToWorld(self.BasePosition*Vector(self.Left and -1 or 1,1,1)))
|
|
self.Models[1][k]:SetAngles(self:LocalToWorldAngles(Angle(self.Left and -1 or 1,1,1)))
|
|
self.Models[1][k]:SetParent(self)
|
|
end
|
|
end
|
|
self.Models.have = true
|
|
self.ModelsCreated = true
|
|
else
|
|
--TODO
|
|
if self.AutostopPresent then
|
|
if IsValid(self.Models[1]["autostop"]) then
|
|
self.Models[1]["autostop"]:SetPoseParameter("position",self:Animate("Autostop", self:GetNW2Bool("Autostop") and 1 or 0, 0,1, 0.4,false))
|
|
end
|
|
end
|
|
|
|
|
|
self.Sig = self:GetNW2String("Signal","")
|
|
self.Num = self:GetNW2String("Number",nil)
|
|
if self.OldNum ~= self.Num then
|
|
self.NextNumWork = CurTime() + 1
|
|
end
|
|
self.OldNum = self.Num
|
|
|
|
if (self.NextNumWork or CurTime()) - CurTime() >= 0 then
|
|
self.Num = ""
|
|
end
|
|
if self.ARSOnly then return end
|
|
local offset = (self.RenderOffset[self.LightType] or Vector(0,0,0))
|
|
if self.RouteNumberOffset then offset = offset + self.RouteNumberOffset*Vector(self.Left and -1 or 1,1) end
|
|
local ID = 0
|
|
local ID2 = 0
|
|
local first = true
|
|
for _,v in ipairs(self.LensesTBL) do
|
|
local data
|
|
if not self.TrafficLightModels[self.LightType][v] then
|
|
data = self.TrafficLightModels[self.LightType][#v-1]
|
|
else
|
|
data = self.TrafficLightModels[self.LightType][v]
|
|
end
|
|
if not data then continue end
|
|
if first then
|
|
first = false
|
|
else
|
|
offset = offset - Vector(0,0,data[1])
|
|
end
|
|
|
|
--self.NamesOffset = self.NamesOffset + Vector(0,0,data[1])
|
|
if v ~= "M" then
|
|
for i = 1,#v do
|
|
ID2 = ID2 + 1
|
|
if tonumber(self.Sig[ID2]) and self.Signals[ID2].RealState ~= (tonumber(self.Sig[ID2]) > 0) then
|
|
self.Signals[ID2].RealState = tonumber(self.Sig[ID2]) > 0
|
|
self.Signals[ID2].Stop = CurTime() + 0.5
|
|
end
|
|
if self.Signals[ID2].Stop and CurTime()-self.Signals[ID2].Stop > 0 then
|
|
self.Signals[ID2].Stop = nil
|
|
end
|
|
local State = self:Animate(ID.."/"..i, ((tonumber(self.Sig[ID2]) == 1 or (tonumber(self.Sig[ID2]) == 2 and (RealTime() % 1.2 > 0.4))) and not self.Signals[ID2].Stop) and 1 or 0, 0,1, 128)
|
|
if not IsValid(self.Models[3][ID..ID2]) and State > 0 then self.Signals[ID2].State = nil end
|
|
if not self.DoubleL then
|
|
self:SetLight(ID,ID2,self.BasePosition*Vector(self.Left and -1 or 1,1,1) + offset + self.LongOffset + data[3][i-1]*Vector(self.Left and -1 or 1,1,1),Angle(0,0,0),self.SignalConverter[v[i]]-1,State,self.Signals[ID2].State ~= State)
|
|
else
|
|
self:SetLight(ID,ID2,self.BasePosition*Vector( 1,1,1) + offset + self.LongOffset + data[3][i-1]*Vector(1,1,1),Angle(0,0,0),self.SignalConverter[v[i]]-1,State,self.Signals[ID2].State ~= State)
|
|
self:SetLight(ID,ID2.."x",self.BasePosition*Vector(-1,1,1) + offset + self.LongOffset + data[3][i-1]*Vector(-1,1,1),Angle(0,0,0),self.SignalConverter[v[i]]-1,State,self.Signals[ID2].State ~= State)
|
|
end
|
|
self.Signals[ID2].State = State
|
|
end
|
|
else
|
|
if Metrostroi.RoutePointer[self.Num[1]] and IsValid(self.Models[1][self.RouteNumber]) then self.Models[1][self.RouteNumber]:SetSkin(Metrostroi.RoutePointer[self.Num[1]]) end
|
|
end
|
|
|
|
ID = ID + 1
|
|
end
|
|
for k,v in pairs(self.RouteNumbers) do
|
|
if k == "sep" then continue end
|
|
local State1 = self:Animate("rou1"..k,self.Num:find(v[1]) and 1 or 0, 0,1, 256)
|
|
local State2
|
|
--if v[3] then
|
|
if v[2] then State2 = self:Animate("rou2"..k,self.Num:find(v[2])and 1 or 0, 0,1, 256) end
|
|
if not IsValid(self.Models[3]["rou1"..k]) and State1 > 0 then
|
|
self.Models[3]["rou1"..k] = ClientsideModel("models/metrostroi/signals/mus/light_lampindicator_"..(v[3] and "numb" or "lamp")..".mdl",RENDERGROUP_OPAQUE)
|
|
self.Models[3]["rou1"..k]:SetPos(self:LocalToWorld(v.pos + self.OldRouteNumberSetup[4]))
|
|
self.Models[3]["rou1"..k]:SetAngles(self:GetAngles())
|
|
self.Models[3]["rou1"..k]:SetParent(self)
|
|
self.Models[3]["rou1"..k]:SetSkin(v[3] and self.OldRouteNumberSetup[5][v[1]] or self.OldRouteNumberSetup[6][v[1]] or tonumber(v[1])-1)
|
|
self.Models[3]["rou1"..k]:SetRenderMode(RENDERMODE_TRANSCOLOR)
|
|
self.Models[3]["rou1"..k]:SetColor(Color(255,255,255,0))
|
|
end
|
|
if IsValid(self.Models[3]["rou1"..k]) then
|
|
if State1 > 0 then
|
|
self.Models[3]["rou1"..k]:SetColor(Color(255,255,255,State1*255))
|
|
elseif State1 == 0 then
|
|
self.Models[3]["rou1"..k]:Remove()
|
|
end
|
|
end
|
|
if not IsValid(self.Models[3]["rou2"..k]) and v[3] and v[2] and State2 > 0 then
|
|
self.Models[3]["rou2"..k] = ClientsideModel("models/metrostroi/signals/mus/light_lampindicator_numb.mdl",RENDERGROUP_OPAQUE)
|
|
self.Models[3]["rou2"..k]:SetPos(self:LocalToWorld(v.pos + self.OldRouteNumberSetup[4] + Vector(0,0,7.2)))
|
|
self.Models[3]["rou2"..k]:SetAngles(self:GetAngles())
|
|
self.Models[3]["rou2"..k]:SetParent(self)
|
|
self.Models[3]["rou2"..k]:SetSkin(self.OldRouteNumberSetup[5][v[2]] or tonumber(v[2])-1)
|
|
self.Models[3]["rou2"..k]:SetRenderMode(RENDERMODE_TRANSCOLOR)
|
|
self.Models[3]["rou2"..k]:SetColor(Color(255,255,255,0))
|
|
end
|
|
if IsValid(self.Models[3]["rou2"..k]) then
|
|
if State2 > 0 then
|
|
self.Models[3]["rou2"..k]:SetColor(Color(255,255,255,State2*255))
|
|
elseif State2 == 0 then
|
|
self.Models[3]["rou2"..k]:Remove()
|
|
end
|
|
end
|
|
end
|
|
if self.Arrow then
|
|
local State = self:Animate("roua",self.Num:find(self.SpecRouteNumbers[1]) and 1 or 0, 0,1, 256)
|
|
if not IsValid(self.Models[3]["roua"]) and State > 0 then
|
|
self.Models[3]["roua"] = ClientsideModel("models/metrostroi/signals/mus/light_lampindicator_lamp.mdl",RENDERGROUP_OPAQUE)
|
|
self.SpecRouteNumbers.pos = (self.BasePosition+offset-Vector(3,-1,3))-self.RouteNumberOffset+ Vector(10.5,0,-6)
|
|
if self.Left then self.SpecRouteNumbers.pos = self.SpecRouteNumbers.pos*Vector(-0.8,1,0.94) end
|
|
self.Models[3]["roua"]:SetPos(self.Models[1]["roua"]:LocalToWorld(Vector(6.2,0,24.5)))
|
|
self.Models[3]["roua"]:SetAngles(self.Models[1]["roua"]:LocalToWorldAngles(Angle(180,0,0)))
|
|
self.Models[3]["roua"]:SetParent(self)
|
|
if self.Left then
|
|
if self.Num[1] == "L" then
|
|
self.Models[3]["roua"]:SetSkin(self.OldRouteNumberSetup[6]["R"] or 0)
|
|
else
|
|
self.Models[3]["roua"]:SetSkin(self.OldRouteNumberSetup[6]["L"] or 0)
|
|
end
|
|
else
|
|
self.Models[3]["roua"]:SetSkin(self.OldRouteNumberSetup[6][self.Num[1]] or 0)
|
|
end
|
|
self.Models[3]["roua"]:SetRenderMode(RENDERMODE_TRANSCOLOR)
|
|
self.Models[3]["roua"]:SetColor(Color(255,255,255,0))
|
|
end
|
|
if IsValid(self.Models[3]["roua"]) then
|
|
if State > 0 then
|
|
self.Models[3]["roua"]:SetColor(Color(255,255,255,State*255))
|
|
elseif State == 0 then
|
|
self.Models[3]["roua"]:Remove()
|
|
end
|
|
end
|
|
end
|
|
--self.SpecRouteNumbers
|
|
end
|
|
end
|
|
|
|
function ENT:Draw()
|
|
-- Draw model
|
|
self:DrawModel()
|
|
end
|
|
local debug = GetConVar("metrostroi_drawsignaldebug")
|
|
|
|
local ars = {
|
|
{"275 Hz", "0 KM/H"},
|
|
{"N/A Hz", "No frequency"},
|
|
{"275-N/A", "Absolute stop"},
|
|
nil,
|
|
{"225 Hz", "40 KM/H"},
|
|
nil,
|
|
{"175 Hz", "60 KM/H"},
|
|
{"125 Hz", "70 KM/H"},
|
|
{"75 Hz", "80 KM/H"},
|
|
}
|
|
local function enableDebug()
|
|
if debug:GetBool() then
|
|
hook.Add("PostDrawTranslucentRenderables","MetrostroiSignalDebug",function(bDrawingDepth,bDrawingSkybox)
|
|
for _,ent in pairs(ents.FindByClass("gmod_track_signal")) do
|
|
if bDrawingDepth and LocalPlayer():GetPos():Distance(sig:GetPos()) < 384 then
|
|
local pos = sig:LocalToWorld(Vector(48,0,150))
|
|
local ang = sig:LocalToWorldAngles(Angle(0,180,90))
|
|
cam.Start3D2D(pos, ang, 0.25)
|
|
|
|
if sig:GetNW2Bool("Debug",false) then
|
|
surface.SetDrawColor(sig.ARSOnly and 255 or 125, 125, 0, 255)
|
|
surface.DrawRect(0, -60, 364, 210)
|
|
if not sig.ARSOnly then
|
|
surface.DrawRect(0, 155, 240, 170)
|
|
surface.DrawRect(0, 330, 240, 190)
|
|
surface.SetDrawColor(0,0,0, 255)
|
|
surface.DrawRect(245, 155, 119, 365)
|
|
else
|
|
surface.DrawRect(0, 155, 364, 150)
|
|
surface.DrawRect(0, 310, 364, 190)
|
|
end
|
|
|
|
if sig.Name then
|
|
draw.DrawText(Format("Joint main info (%d)",sig:EntIndex()),"Trebuchet24",5,-60,Color(200,0,0,255))
|
|
draw.DrawText("Signal name: "..sig.Name,"Trebuchet24", 15, -40,Color(0,0,0,255))
|
|
draw.DrawText("TrackID: "..sig:GetNW2Int("PosID",0),"Trebuchet24", 25, -20,Color(0,0,0,255))
|
|
draw.DrawText(Format("PosX: %.02f",sig:GetNW2Float("Pos",0)),"Trebuchet24", 135, -20,Color(0,0,0,255))
|
|
draw.DrawText(Format("NextSignalName: %s",sig:GetNW2String("NextSignalName","N/A")),"Trebuchet24", 15, 0,Color(0,0,0,255))
|
|
draw.DrawText(Format("TrackID: %s",sig:GetNW2Int("NextPosID",0)),"Trebuchet24", 25, 20,Color(0,0,0,255))
|
|
draw.DrawText(Format("PosX: %.02f",sig:GetNW2Float("NextPos",0)),"Trebuchet24", 135, 20,Color(0,0,0,255))
|
|
draw.DrawText(Format("Dist: %.02f",sig:GetNW2Float("DistanceToNext",0)),"Trebuchet24", 15, 40,Color(0,0,0,255))
|
|
draw.DrawText(Format("PrevSignalName: %s",sig:GetNW2String("PrevSignalName","N/A")),"Trebuchet24", 15, 60,Color(0,0,0,255))
|
|
draw.DrawText(Format("TrackID: %s",sig:GetNW2Int("PrevPosID",0)),"Trebuchet24", 25, 80,Color(0,0,0,255))
|
|
draw.DrawText(Format("PosX: %.02f",sig:GetNW2Float("PrevPos",0)),"Trebuchet24", 135, 80,Color(0,0,0,255))
|
|
draw.DrawText(Format("DistPrev: %.02f",sig:GetNW2Float("DistanceToPrev",0)),"Trebuchet24", 15, 100,Color(0,0,0,255))
|
|
draw.DrawText(Format("Current route: %d",sig:GetNW2Int("CurrentRoute",-1)),"Trebuchet24", 15, 120,Color(0,0,0,255))
|
|
|
|
draw.DrawText("AB info","Trebuchet24",5,160,Color(200,0,0,255))
|
|
draw.DrawText(Format("Occupied: %s",sig:GetNW2Bool("Occupied",false) and "Y" or "N"),"Trebuchet24",5,180,Color(0,0,0,255))
|
|
draw.DrawText(Format("Linked to controller: %s",sig:GetNW2Bool("LinkedToController",false) and "Y" or "N"),"Trebuchet24",5,200,Color(0,0,0,255))
|
|
draw.DrawText(Format("Num: %d",sig:GetNW2Int("ControllersNumber",0)),"Trebuchet24",10,220,Color(0,0,0,255))
|
|
draw.DrawText(Format("Controller logic: %s",sig:GetNW2Bool("BlockedByController",false) and "Y" or "N"),"Trebuchet24",5,240,Color(0,0,0,255))
|
|
draw.DrawText(Format("Autostop: %s",not sig.ARSOnly and sig.AutostopPresent and (sig:GetNW2Bool("Autostop") and "Up" or "Down") or "No present"),"Trebuchet24",5,260,Color(0,0,0,255))
|
|
draw.DrawText(Format("2/6: %s",sig:GetNW2Bool("2/6",false) and "Y" or "N"),"Trebuchet24",5,280,Color(0,0,0,255))
|
|
draw.DrawText(Format("FreeBS: %d",sig:GetNW2Int("FreeBS")),"Trebuchet24",5,300,Color(0,0,0,255))
|
|
|
|
draw.DrawText("ARS info","Trebuchet24",5,335,Color(200,0,0,255))
|
|
local num = 0
|
|
for i,tbl in pairs(ars) do
|
|
if not tbl then continue end
|
|
if sig:GetNW2Bool("CurrentARS"..(i-1),false) then
|
|
draw.DrawText(Format("(% s)",tbl[1]),"Trebuchet24",5,355+num*20,Color(0,100,0,255))
|
|
draw.DrawText(Format("%s",tbl[2]),"Trebuchet24",105,355+num*20,Color(0,100,0,255))
|
|
else
|
|
draw.DrawText(Format("(% s)",tbl[1]),"Trebuchet24",5,355+num*20,Color(0,0,0,255))
|
|
draw.DrawText(Format("%s",tbl[2]),"Trebuchet24",105,355+num*20,Color(0,0,0,255))
|
|
end
|
|
num = num+1
|
|
end
|
|
if sig:GetNW2Bool("CurrentARS325",false) or sig:GetNW2Bool("CurrentARS325_2",false) then
|
|
draw.DrawText("(325 Hz)","Trebuchet24",5,355+num*20,Color(0,100,0,255))
|
|
draw.DrawText(Format("LN:%s Apr0:%s",sig:GetNW2Bool("CurrentARS325",false) and "Y" or "N",sig:GetNW2Bool("CurrentARS325_2",false) and "Y" or "N"),"Trebuchet24",105,355+num*20,Color(0,100,0,255))
|
|
else
|
|
draw.DrawText("(325 Hz)","Trebuchet24",5,355+num*20,Color(0,0,0,255))
|
|
draw.DrawText(Format("LN:%s Apr0:%s",sig:GetNW2Bool("CurrentARS325",false) and "Y" or "N",sig:GetNW2Bool("CurrentARS325_2",false) and "Y" or "N"),"Trebuchet24",105,355+num*20,Color(0,0,0,255))
|
|
end
|
|
|
|
if not sig.ARSOnly then
|
|
draw.DrawText("Signal info","Trebuchet24",250,160,Color(200,0,0,255))
|
|
local ID = 0
|
|
local ID2 = 0
|
|
local first = true
|
|
for _,v in ipairs(sig.LensesTBL) do
|
|
local data
|
|
if not sig.TrafficLightModels[sig.LightType][v] then
|
|
data = sig.TrafficLightModels[sig.LightType][#v-1]
|
|
else
|
|
data = sig.TrafficLightModels[sig.LightType][v]
|
|
end
|
|
if not data then continue end
|
|
|
|
--sig.NamesOffset = sig.NamesOffset + Vector(0,0,data[1])
|
|
local cols = {
|
|
R = Color(200,0,0),
|
|
Y = Color(200,200,0),
|
|
G = Color(0,200,0),
|
|
W = Color(200,200,200),
|
|
B = Color(0,0,200),
|
|
}
|
|
if v ~= "M" then
|
|
for i = 1,#v do
|
|
ID2 = ID2 + 1
|
|
local State = tonumber(sig.Sig[ID2]) == 1 and "X" or (tonumber(sig.Sig[ID2]) == 2 and (RealTime() % 1.2 > 0.4)) and "B" or false
|
|
draw.DrawText(Format(v[i],sig:EntIndex()),"Trebuchet24",250,160 + ID*20 + ID2*20,cols[v[i]])
|
|
if State then
|
|
draw.DrawText(State,"Trebuchet24",280,160 + ID*20 + ID2*20,cols[v[i]])
|
|
end
|
|
end
|
|
else
|
|
ID2 = ID2 + 1
|
|
draw.DrawText("M","Trebuchet24",250,160 + ID*20 + ID2*20,Color(200,200,200))
|
|
draw.DrawText(sig.Num or "none","Trebuchet24",280,160 + ID*20 + ID2*20,Color(200,200,200))
|
|
|
|
--if Metrostroi.RoutePointer[sig.Num[1]] then sig.Models[1][sig.RouteNumber]:SetSkin(Metrostroi.RoutePointer[sig.Num[1]]) end
|
|
end
|
|
|
|
ID = ID + 1
|
|
end
|
|
end
|
|
else
|
|
draw.DrawText("No data...","Trebuchet24",5,0,Color(0,0,0,255))
|
|
end
|
|
else
|
|
surface.SetDrawColor(sig.ARSOnly and 255 or 125, 125, 0, 255)
|
|
surface.DrawRect(0, 0, 364, 25)
|
|
draw.DrawText("Debug disabled...","Trebuchet24",5,0,Color(0,0,0,255))
|
|
end
|
|
cam.End3D2D()
|
|
end
|
|
end
|
|
end)
|
|
else
|
|
hook.Remove("PostDrawTranslucentRenderables","MetrostroiSignalDebug")
|
|
end
|
|
end
|
|
hook.Remove("PostDrawTranslucentRenderables","MetrostroiSignalDebug")
|
|
cvars.AddChangeCallback( "metrostroi_drawsignaldebug", enableDebug)
|
|
enableDebug()
|
|
|
|
Metrostroi.OptimisationPatch() |