1
0
mirror of https://github.com/metrostroi-repo/MetrostroiAddon.git synced 2026-05-02 00:42:29 +00:00
This commit is contained in:
g_brzhezinskiy
2021-01-02 12:51:45 +03:00
commit 1d05caf866
613 changed files with 337020 additions and 0 deletions

View File

@@ -0,0 +1,700 @@
include("shared.lua")
--------------------------------------------------------------------------------
ENT.ClientProps = {}
ENT.ButtonMap = {}
ENT.AutoAnims = {}
ENT.AutoAnimNames = {}
ENT.ClientSounds = {}
ENT.ClientPropsInitialized = false
ENT.ButtonMap["ARM"] = {
pos = Vector(-4.9,9.1,50.3),
ang = Angle(0,-90-1,90),
width = 800,
height = 600,
scale = 0.02*1.2,
mouse = true
}
ENT.ClientProps["ARMPK"] = {
model = "models/cyber_metrostroi/pc_arm/pc_screen.mdl",
pos = Vector(-5,0,31.2),
ang = Angle(0,180,0),
bscale = Vector(4/3,1,1),
}
ENT.ClientProps["ARMMonitor"] = {
model = "models/cyber_metrostroi/pc_arm/pc_body.mdl",
pos = Vector(-5,15,0),
ang = Angle(0,180,0),
bscale = Vector(4/3,1,1),
}
ENT.ClientProps["ARMKeyboard"] = {
model = "models/cyber_metrostroi/pc_arm/pc_keyboard.mdl",
pos = Vector(-15,-2,31),
ang = Angle(0,180,0),
}
ENT.ClientProps["ARMMouse"] = {
model = "models/cyber_metrostroi/pc_arm/pc_mouse.mdl",
pos = Vector(-18,-20,32),
ang = Angle(0,180,0),
}
ENT.ClientProps["ARMBreen"] = {
model = "models/props_combine/breenglobe.mdl",
pos = Vector(-11,30,39.5),
ang = Angle(0,-180+45,0),
}
function ENT:Initialize()
self.BaseClass.Initialize(self)
self.ARM = self:CreateRT("ARM",1024,1024)
for k,v in pairs(self.Types) do
for i,tex in pairs(v) do
if type(tex) == "table" and type(tex[1]) == "string" then
tex.mat = surface.GetTextureID(tex[1])
end
end
end
end
function ENT:CamMoved()
self:HandleMouse(false)
gui.EnableScreenClicker(self.CurrentCamera ~= 0)
end
function ENT:Think()
self.BaseClass.Think(self)
if not self.RenderClientEnts or self.CreatingCSEnts then
return
end
if not self.ARM then return end
--self.MouseX = 0
--self.MouseY = 0
self.MouseX = self:GetNW2Int("CursorX",0)
self.MouseY = self:GetNW2Int("CursorY",0)
render.PushRenderTarget(self.ARM,0,0,1024, 1024)
render.Clear(0, 0, 0, 0)
cam.Start2D()
render.OverrideAlphaWriteEnable(true, true)
surface.SetDrawColor(0,0,0)
surface.DrawRect(0,0,800,600)
self:ARMMonitor()
cam.End2D()
render.PopRenderTarget()
end
function ENT:Draw()
self.BaseClass.Draw(self)
end
function ENT:DrawPost()
self.RTMaterial:SetTexture("$basetexture", self.ARM)
self:DrawOnPanel("ARM",function(...)
surface.SetMaterial(self.RTMaterial)
surface.SetDrawColor(255,255,255)
surface.DrawTexturedRectRotated(512,512,1024,1024,0)
end)
end
local gray = Color(100,100,100)
local black = Color(0,0,0)
local white = Color(150,150,150)
local green = Color(0,50,0)
local function GetTextures(segm,typ)
return segm[typ],segm.maintex or segm[typ]
end
--Get texture Width and Height
local function GetWH(segm,typ)
local tex,dtex = GetTextures(segm,typ)
return tex.w or dtex.w,tex.h or dtex.h
end
--Get real(original) texture Width and Height
local function GetRWH(segm,typ)
local tex,dtex = GetTextures(segm,typ)
return tex.rw or dtex.rw,tex.rh or dtex.rh
end
--Get X and Y adds
local function GetXYA(segm,typ)
local tex,dtex = GetTextures(segm,typ)
return tex.xa or dtex.xa or 0,tex.ya or dtex.ya or 0
end
local function GetXY(x,y)
return 100+x*36,100+y*70
end
local function drawSegment(w,h,u0,v0,u1,v1,segm,typ,align)
--local segm = self.Types[typ]
if not segm or not segm[typ] then return end
local tex,dtex = GetTextures(segm,typ)
if dtex.mat then
local sx,sy = GetXY(w,h)
local sw,sh = GetWH(segm,typ)
local sxa = tex.x or dtex.x or 0
local xa,ya = GetXYA(segm,typ)
local rw,rh = GetRWH(segm,typ)
surface.SetDrawColor(tex.col or dtex.col or white)
surface.SetTexture(tex.mat or dtex.mat)
surface.DrawTexturedRectUV(sx+xa+sxa*u0,sy+ya-(rh-8)*v0,rw,rh,(rw/sw)*u0,(rh/sh)*v0,(rw/sw)*u1,(rh/sh)*v1)
end
end
local function drawElement(sx,sy,u0,v0,u1,v1,segm,typ,col)
--local segm = self.Types[typ]
if not segm or not segm[typ] then return end
local tex = segm[typ]
local dtex = segm.maintex or tex
--local sx,sy = 100+w*36,100+h*70
local sw,sh = tex.w or dtex.w,tex.h or dtex.h
local sxa = tex.x or dtex.x or 0
local xa,ya = tex.xa or dtex.xa or 0,tex.ya or dtex.ya or 0
local rw,rh = tex.rw or dtex.rw,tex.rh or dtex.rh
surface.SetDrawColor(col or tex.col or dtex.col or white)
surface.SetTexture(tex.mat or dtex.mat)
surface.DrawTexturedRectUV(sx+xa+sxa*u0,sy+ya-(rh-8)*v0 ,rw,rh,(rw/sw)*u0,(rh/sh)*v0,(rw/sw)*u1,(rh/sh)*v1)
end
local mouse = surface.GetTextureID("gui/info")
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("Arial10","Arial",10,400)
createFont("Arial20","Arial",20,800)
local colorConverter = {
r = Color(0,0,0),
y = Color(240,240,71),
g = Color(41,202,26),
b = Color(26,84,202),
w = Color(255,255,255),
}
local function GetSegmPos(segm,alt)
local x,y = segm.x,segm.y
local segmt = segm.segm
local u0,v0,u1,v1 = 0,0,1,1
if segm.invertX then u0,u1 = 1,0 end
if segm.invertY then v0,v1 = 1,0 end
if alt == nil then
return GetXY(x+segm.width*u0,y)
elseif alt == false and segmt.next_m then
return GetXY(x+segmt.next_m.x-segm.width*u0,y+segmt.next_m.y)
--print(123,x,y)
elseif alt and segmt.next_a then
return GetXY(x+segmt.next_a.x*u1-segmt.next_a.x*u0+segmt.width*u0,y+segmt.next_a.y*v1-segmt.next_a.y*v0)
end
end
local function ARMFindNextSegm(station,csegm,alt,dir,deb)
if dir then
if alt and not csegm.segm.next_a then return end
if not alt and not csegm.segm.next_m then return end
for segmid,segm in ipairs(station) do
if segm == csegm then continue end
if segm.x <= csegm.x then continue end
local txa,tya = GetSegmPos(csegm,alt)
local tx,ty = GetXY(csegm.x+csegm.width*(csegm.invertX or 0),csegm.y)
if not txa then continue end
--if tx then print(1,segm.x,segm.y,GetSegmPos2(csegm,alt),csegm.invertX,csegm.invertY) end
local sx,sy = GetXY(segm.x+segm.width*(segm.invertX or 0),segm.y)
--if not alt then print(2,x,y,sx,sy,tx,ty,txa,tya) end
if sx == tx and sy == ty then return segm,sx,sy end
if sx == txa and sy == tya then return segm,sx,sy end
sx,sy = GetSegmPos(segm,false)
--if sx and sx == tx and sy == ty then return segm,false end
--if deb then print(sx,x) end
if sx and sx == txa and sy == tya then return segm,sx,sy end
sx,sy = GetSegmPos(segm,true)
--if sx and sx == tx and sy == ty then return segm,false end
if sx and sx == txa and sy == tya and (not alt or segm.y ~= csegm.y) then return segm,sx,sy end
end
else
for segmid,segm in ipairs(station) do
if segm == csegm then continue end
if segm.x >= csegm.x then continue end
local txa,tya = GetSegmPos(segm,alt)
local tx,ty = GetXY(segm.x+segm.width*(segm.invertX or 0),segm.y)
if not txa then continue end
local sx,sy = GetXY(csegm.x+csegm.width*(csegm.invertX or 0),csegm.y)
if sx == tx and sy == ty then return segm,sx,sy end
if sx == txa and sy == tya then return segm,sx,sy end
sx,sy = GetSegmPos(csegm,false)
if sx and sx == txa and sy == tya then return segm,sx,sy end
sx,sy = GetSegmPos(csegm,true)
if sx and sx == txa and sy == tya and (not alt or segm.y ~= csegm.y) then return segm,sx,sy end
end
--[[ for segmid,segm in ipairs(station) do
if segm == csegm then continue end
if segm.x >= csegm.x then continue end
local txa,tya = GetSegmPos(segm,alt)
local tx,ty = GetXY(segm.x+segm.width*(segm.invertX or 0),segm.y)
if not txa then continue end
--if tx then print(1,segm.x,segm.y,GetSegmPos2(csegm,alt),csegm.invertX,csegm.invertY) end
local sx,sy = GetXY(csegm.x+csegm.width*(csegm.invertX or 0),csegm.y)
--if not alt then print(2,x,y,sx,sy,tx,ty,txa,tya) end
if sx == tx and sy == ty then return segm end
if sx == txa and sy == tya then return segm end
sx,sy = GetSegmPos(csegm,false)
--if sx and sx == tx and sy == ty then return segm,false end
--if deb then print(sx,x) end
if sx and sx == txa and sy == tya then return segm end
sx,sy = GetSegmPos(csegm,true)
--if alt then print(3,x,y,sx,sy,tx,ty) end
--if sx and sx == tx and sy == ty then return segm,false end
if sx and sx == txa and sy == tya and (not alt or segm.y ~= csegm.y) then return segm end
end--]]
end
end
local function ARMSetNextCompare(posX,posY,segm,nsegm)
local xp,yp = GetSegmPos(segm)
local x,y = GetSegmPos(nsegm)
if sx and posX == x and posY == y then
nsegm.prev = segm
return true
end
sx,sy = GetSegmPos(nsegm,false)
if sx and posX == sx and posY == sy then
nsegm.next_m = segm
return true
end
if not nsegm.segm.next_a then return end
sx,sy = GetSegmPos(nsegm,true)
if x ~= xp and y ~= yp and sx and posX == sx and posY == sy then
nsegm.next_a = segm
if segm.id == 29 then
local x1,y1 = GetSegmPos(nsegm)
local x2,y2 = GetSegmPos(segm)
print(-2,x1,y1,x2,y2)
end
return true
end
end
local function ARMSetNext(station)
for csegmid,csegm in ipairs(station) do
for segmid,segm in ipairs(station) do
if segm == csegm then continue end
local posX,posY = GetSegmPos(csegm)
if ARMSetNextCompare(posX,posY,csegm,segm) then
csegm.prev = segm
--break
end
local posOX,posOY = GetSegmPos(csegm,false)
if ARMSetNextCompare(posOX,posOY,csegm,segm) then
csegm.next_m = segm
--break
end
local posAЧ,posAY = GetSegmPos(segm)
if not csegm.segm.next_a or posX == posAX or posY == posAY then continue end
posOX,posOY = GetSegmPos(csegm,true)
if ARMSetNextCompare(posOX,posOY,csegm,segm) then
csegm.next_a = segm
--break
end
end
end
end
function ENT:ARMMonitor()
if self.FilterMag then
render.PopFilterMag()
render.PopFilterMin()
end
render.PushFilterMag( TEXFILTER.POINT )
render.PushFilterMin( TEXFILTER.POINT )
self.FilterMag = true
surface.SetDrawColor(gray)
surface.DrawRect(0,0,800,600)
local station = self:GetNW2Int("ARM:Station",0)
--draw.SimpleText("АРМ ДЫЫСЦЫПЫ","Metrostroi_BUKPSpeed",400, 300,Color(220,0,0),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER)
if station > 0 and Metrostroi.ARMConfigGenerated and Metrostroi.ARMConfigGenerated[station] then
local armTable = Metrostroi.ARMConfigGenerated[station]
for id,segm in ipairs(armTable) do
local u0,v0,u1,v1 = 0,0,1,1
if segm.invertX then u0,u1 = 1,0 end
if segm.invertY then v0,v1 = 1,0 end
drawSegment(segm.x,segm.y,u0,v0,u1,v1,segm.segm,"maintex")
--[[
local w,h = GetXY(segm.x+segm.width*u0,segm.y)
surface.SetDrawColor(Color(255,0,0))
surface.DrawLine(w+5*u1-5*u0,h,w,h)
surface.DrawLine(w,h+5,w,h)
local w,h = GetSegmPos(segm,false)
surface.SetDrawColor(Color(255,255,0))
surface.DrawLine(w-6*u1+6*u0,h,w,h)
surface.DrawLine(w,h-6,w,h)
local w,h = GetSegmPos(segm,true)
if w then
surface.SetDrawColor(Color(0,255,0))
surface.DrawLine(w-6*u1+6*u0,h,w,h)
surface.DrawLine(w,h-6*v1+6*v0,w,h)
end--]]
end
local w,h = 0,0
for id,segm in ipairs(armTable) do
local u0,v0,u1,v1 = 0,0,1,1
if segm.invertX then u0,u1 = 1,0 end
if segm.invertY then v0,v1 = 1,0 end
if Metrostroi.GetARMInfo(station,id,"occup2") then
drawSegment(segm.x,segm.y,u0,v0,u1,v1,segm.segm,"occup_x")
end
if Metrostroi.GetARMInfo(station,id,"switch_m") then
if Metrostroi.GetARMInfo(station,id,"occup") then drawSegment(segm.x,segm.y,u0,v0,u1,v1,segm.segm,"occup_m")
elseif Metrostroi.GetARMInfo(station,id,"route") then drawSegment(segm.x,segm.y,u0,v0,u1,v1,segm.segm,"route_m") end
drawSegment(segm.x,segm.y,u0,v0,u1,v1,segm.segm,"switch_m")
elseif Metrostroi.GetARMInfo(station,id,"switch_a") then
if Metrostroi.GetARMInfo(station,id,"occup") then drawSegment(segm.x,segm.y,u0,v0,u1,v1,segm.segm,"occup_a")
elseif Metrostroi.GetARMInfo(station,id,"route") then drawSegment(segm.x,segm.y,u0,v0,u1,v1,segm.segm,"route_a") end
drawSegment(segm.x,segm.y,u0,v0,u1,v1,segm.segm,"switch_a")
elseif Metrostroi.GetARMInfo(station,id,"switch_na") then
if Metrostroi.GetARMInfo(station,id,"occup") then
drawSegment(segm.x,segm.y,u0,v0,u1,v1,segm.segm,"occup_m")
drawSegment(segm.x,segm.y,u0,v0,u1,v1,segm.segm,"occup_a")
end
drawSegment(segm.x,segm.y,u0,v0,u1,v1,segm.segm,"switch_an")
drawSegment(segm.x,segm.y,u0,v0,u1,v1,segm.segm,"switch_mn")
else
if Metrostroi.GetARMInfo(station,id,"occup") then drawSegment(segm.x,segm.y,u0,v0,u1,v1,segm.segm,"occup_m")
elseif Metrostroi.GetARMInfo(station,id,"route") then drawSegment(segm.x,segm.y,u0,v0,u1,v1,segm.segm,"route_m") end
end
if segm.signal1 then
local sig = segm.signal1
local typ = self.Types["tl_"..sig.type]
local x,y = 100+(segm.x+segm.width)*36,100+segm.y*70-(sig.top and -26 or 15)
local rw,rh = GetRWH(typ,"maintex")
local sx,sy = x-rw-2,y-rh-2
draw.SimpleText(sig.name,"Metrostroi_Arial10",x, y-(sig.top and -7 or 15),Color(0,0,0),TEXT_ALIGN_RIGHT,TEXT_ALIGN_BOTTOM)
drawElement(sx,sy,0,0,1,1,typ,"maintex")
local colors = Metrostroi.GetARMInfo(station,id,"signal1") or ""
if sig.type > 1 and Metrostroi.GetARMInfo(station,id,"signal1I") then
drawElement(sx+13*(sig.type-1),sy,0,0,1,1,typ,"full",colorConverter.w)
end
if sig.type > 2 and Metrostroi.GetARMInfo(station,id,"signal1Y") then
drawElement(sx+13*(sig.type-2),sy,0,0,1,1,typ,"full",colorConverter.y)
end
if colors ~= "" and #colors == 1 then
local color = colors:lower()
drawElement(sx,sy,0,0,1,1,typ,"full",colorConverter[color] or Color(0,0,0))
elseif colors ~= "" and #colors == 2 then
local color = colors:lower()
drawElement(sx,sy,0,0,1,1,typ,"h1",colorConverter[color[1]] or Color(0,0,0))
drawElement(sx,sy,0,0,1,1,typ,"h2",colorConverter[color[2]] or Color(0,0,0))
end
end
if segm.signal2 then
local sig = segm.signal2
local typ = self.Types["tl_"..sig.type]
local rw,rh = GetRWH(typ,"maintex")
local x,y = 100+(segm.x)*36+2,100+segm.y*70+(sig.top and -38 or 3)
local sx,sy = x-1,y+rh
draw.SimpleText(sig.name,"Metrostroi_Arial10",x, y+(sig.top and -2 or 20),Color(0,0,0),TEXT_ALIGN_LEFT,TEXT_ALIGN_TOP)
drawElement(sx,sy,1,1,0,0,typ,"maintex")
local colors = Metrostroi.GetARMInfo(station,id,"signal2") or ""
if sig.type > 1 and Metrostroi.GetARMInfo(station,id,"signal2I") then
drawElement(sx+rw-12-13*(sig.type-1),sy,1,1,0,0,typ,"full",colorConverter.w)
end
if sig.type > 2 and Metrostroi.GetARMInfo(station,id,"signal2Y") then
drawElement(sx+rw-12-13*(sig.type-2),sy,1,1,0,0,typ,"full",colorConverter.y)
end
if colors ~= "" and #colors == 1 then
local color = colors:lower()
drawElement(sx+rw-12,sy,1,1,0,0,typ,"full",colorConverter[color] or Color(0,0,0))
elseif colors ~= "" and #colors == 2 then
local color = colors:lower()
drawElement(sx+rw-12,sy,1,1,0,0,typ,"h1",colorConverter[color[1]] or Color(0,0,0))
drawElement(sx+rw-12,sy,1,1,0,0,typ,"h2",colorConverter[color[2]] or Color(0,0,0))
end
end
end
for id,button in ipairs(armTable.buttons) do
local sx,sy = 100+button.x*36,100+button.y*70
local sw,sh = 15,25
local xa,ya = 3,12
if button.type=="r" then
sw,sh = 15,25
xa,ya = 3,12
end
local x,y = sx+xa,sy+ya
if Metrostroi.GetARMInfo(station,1000+id,"buttonSelected") then
surface.SetDrawColor(Color(80,80,180))
elseif Metrostroi.GetARMInfo(station,1000+id,"buttonPressable") then
surface.SetDrawColor(Color(220,220,220))
else
surface.SetDrawColor(Color(120,120,120))
end
surface.DrawRect(x,y,sw,sh)
Metrostroi.DrawLine(x,y,x,y+sh,Color(240,240,240),2)
Metrostroi.DrawLine(x-1,y,x+sw,y,Color(240,240,240),2)
Metrostroi.DrawLine(x+sw,y,x+sw,y+sh,Color(60,60,60),2)
Metrostroi.DrawLine(x,y+sh,x+sw+1,y+sh,Color(60,60,60),2)
end
end
for i,v in ipairs(Metrostroi.ARMConfigGenerated) do
if i == station then
surface.SetDrawColor(Color(110,140,170))
elseif math.InRangeXYR(self.MouseX,self.MouseY,20+(i-1)*30,20,30,20) then
surface.SetDrawColor(Color(80,110,140))
else
surface.SetDrawColor(Color(100,130,160))
end
surface.DrawRect(20+(i-1)*31,20,30,20)
draw.SimpleText(v.shortname or v.id,"Metrostroi_Arial20",35+(i-1)*31, 30,Color(40,60,170),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER)
end
--if self.CurrentCamera == 0 then
surface.SetDrawColor(255,255,255)
surface.SetTexture(mouse)
surface.DrawTexturedRectRotated(self.MouseX,self.MouseY,8,8,0)
--end
surface.SetDrawColor(0,0,0,200)
surface.DrawRect(0,0,800,600)
render.PopFilterMag()
render.PopFilterMin()
self.FilterMag = false
--[=[
local iter = 0
local function ARMFindSegmSignals(station,segm,dir,signals,checked,restbl,trace,NextAlt)
if not restbl then restbl = {} end
if not checked then checked = {} end
if not trace then trace = {} end
if checked[segm] then return end
checked[segm] = true
local segmIndex = table.insert(trace,{segm.id})
--trace[segm] = true
iter = iter + 1
if iter > 10000 then ARMGenError(Format("Routes generation error. Max iter reached!"),true) return false end
local segmt = segm.segm
local segmM,segmA = segmt.next_m,segmt.next_a
if not segmM then return end
local NextM = ARMFindNextSegm(station,segm,not NextAlt,dir)
local NextA = ARMFindNextSegm(station,segm,NextAlt,dir)
local xp,yp = GetXY(segm.x,segm.y)
if NextA then
local trace= table.Copy(trace)
trace[segmIndex][2] = true
local xn,yn = GetXY(NextA.x,NextA.y)
local xa1,ya1 = GetSegmPos(segm,true)
local xa2,ya2 = GetSegmPos(NextA,true)
--trace[segmIndex][2] = true
local nxt = xa1==xn and ya1==yn or
xa2==xn and ya2==yn or
xa1==xp and ya1==yp or
xa2==xp and ya2==yp or
xa1 and xa2 and xa1==xa2 and ya1==ya2
--MsgN(Format("->A\n",segm.x,segm.y))
local signal = dir and NextA.signal2 or NextA.signal1
--print("A",segm.x,segm.y,NextA.x,NextA.y,signal and signal.name,dir)
if signal and table.HasValue(signals,signal.name) then--and not segmOnA.invertX then
table.insert(restbl,{signal,table.Copy(trace)})
end
ARMFindSegmSignals(station,NextA,dir,signals,checked,restbl,trace,true)
end
if NextM then
local xn,yn = GetXY(NextM.x,NextM.y)
local xa1,ya1 = GetSegmPos(segm,true)
local xa2,ya2 = GetSegmPos(NextM,true)
local nxt = xa1==xn and ya1==yn or
xa2==xn and ya2==yn or
xa1==xp and ya1==yp or
xa2==xp and ya2==yp or
xa1 and xa2 and xa1==xa2 and ya1==ya2
local signal = dir and NextM.signal2 or NextM.signal1
--print("M",segm.x,segm.y,NextM.x,NextM.y,signal and signal.name,dir)
if signal and table.HasValue(signals,signal.name) then--and not segmOnA.invertX then
table.insert(restbl,{signal,table.Copy(trace)})
end
ARMFindSegmSignals(station,NextM,dir,signals,checked,restbl,table.Copy(trace))
end
return restbl
end
local station = Metrostroi.ARMConfigGenerated[station]
for _,button in pairs(station.buttons,station.routes["PT64"]) do
if button.type == "r" and station.routes[button.signal] then
--button.pressable = true
local results = ARMFindSegmSignals(station,button.segm,false,station.routes[button.signal])
if #results == 0 then
results = ARMFindSegmSignals(station,button.segm,true,station.routes[button.signal])
end
for k,v in pairs(results) do
local i = 0
for k,v in pairs(v[2]) do
print(v[2])
end
end
--print(results[1][1].name,results[1][1].segm)--]]
--button.routes = results
end
end--]=]
--[=[
local x = 0
local founded = true
local stat = Metrostroi.ARMConfigGenerated[station]
local maxd = 3
local x = 26-- or math.ceil((CurTime()%10)/10*#stat)
local dir = true-- or CurTime()%20 > 10
local function findt(station,segm,dir,i,depth,px,py )
depth = depth or 0
i = i or 0
local segmt = segm.segm
local segmM,segmA = segmt.next_m,segmt.next_a
local NextM,NextMX,NextMY = ARMFindNextSegm(station,segm,false,dir)
local NextA,NextAX,NextAY = ARMFindNextSegm(station,segm,true,dir)
local xp,yp = GetXY(segm.x,segm.y)
draw.SimpleText(i,"Metrostroi_Arial20",xp,yp,Color(255,0,0),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER)
draw.SimpleText(Format("%.1f:%.1f",segm.x,segm.y),"Metrostroi_Arial10",xp,yp-20,Color(255,0,0),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER)
local xa1,ya1 = GetSegmPos(segm,true)
if i==4 then print(xa1,ya1,px,py,xa1 == px and ya1 == py) end
local alt = px and py ~= yp and xa1 == px and ya1 == py
if NextA and depth+1 < maxd then
--if i==3 then print(1) end
local xn,yn = GetXY(NextA.x,NextA.y)
local xa2,ya2 = GetSegmPos(NextA,true)
local nalt = xa1==xn and ya1==yn or
xa2==xn and ya2==yn or
xa1==xp and ya1==yp or
xa2==xp and ya2==yp or
xa1 and xa2 and xa1==xa2 and ya1==ya2
if nalt or alt then surface.SetDrawColor(Color(255,0,0))
else surface.SetDrawColor(Color(0,255,0)) end
surface.DrawLine(px or xp,py or yp,NextAX or xn,NextAY or yn)
if findt(station,NextA,dir,i+1,depth+1,NextAX,NextAY) then return end
--return true
--if i==5 then print("RES",segm.x,segm.y,NextA.x,NextA.y) end
end
if NextM and depth < maxd then
local xn,yn = GetXY(NextM.x,NextM.y)
local xa2,ya2 = GetSegmPos(NextM,true)
local nalt = xa1==xn and ya1==yn or
xa2==xn and ya2==yn or
xa1==xp and ya1==yp or
xa2==xp and ya2==yp or
xa1 and xa2 and xa1==xa2 and ya1==ya2
if alt then surface.SetDrawColor(Color(255,255,0))
else surface.SetDrawColor(Color(0,255,0)) end
surface.DrawLine(px or xp,py or yp,NextMX or xn,NextMY or yn)
if findt(station,NextM,dir,i+1,depth,NextMX,NextMY) then return end
end
end
--findt(stat,stat[x],dir)--]=]
---[==[
if Metrostroi.ARMConfigGenerated[station] then
ARMSetNext(Metrostroi.ARMConfigGenerated[station])
--[=[ for id,segm in ipairs(Metrostroi.ARMConfigGenerated[station]) do
local ws,hs = GetSegmPos(segm)
draw.SimpleText(segm.id,"Metrostroi_Arial20",ws,hs-15--[[ *(math.random()*5)--]] ,Color(0,255,0),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER)
if segm.next_m then
local w,h = GetSegmPos(segm.next_m)
surface.SetDrawColor(Color(0,255,0))
surface.DrawLine(ws,hs,w,h)
surface.DrawLine(ws-6,hs-6,ws+6,hs+6)
surface.DrawLine(ws-6,hs+6,ws+6,hs-6)
surface.DrawLine(w-6,h-2,w+6,h+2)
surface.DrawLine(w-6,h+2,w+6,h-2)
else
local w,h = GetSegmPos(segm)
w = w+segm.width*36/2
surface.SetDrawColor(Color(255,0,255))
surface.DrawLine(w-4,h-4,w+4,h+4)
surface.DrawLine(w-4,h+4,w+4,h-4)
continue
end
if segm.next_a then
local w,h = GetSegmPos(segm.next_a)
draw.SimpleText(segm.id,"Metrostroi_Arial20",w,h+15,Color(255,0,0),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER)
surface.SetDrawColor(Color(255,0,0))
surface.DrawLine(ws,hs,w,h)
surface.DrawLine(ws-7,hs-4,ws+7,hs+4)
surface.DrawLine(ws-7,hs+4,ws+7,hs-4)
surface.DrawLine(w-7,h-2,w+7,h+2)
surface.DrawLine(w-7,h+2,w+7,h-2)
end
end--]=]
local x = 0
local founded = true
local stat = Metrostroi.ARMConfigGenerated[station]
local maxd = 2
local x = 21-- or math.ceil((CurTime()%10)/10*#stat)
local dir = true-- or CurTime()%20 > 10
local function findt(station,segm,dir,i,depth,last )
depth = depth or 0
i = i or 0
local segmP = segm.prev
local segmM,segmA = segm.next_m,segm.next_a
local x,y = GetXY(segm.x,segm.y)
draw.SimpleText(i,"Metrostroi_Arial20",x,y,Color(255,0,0),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER)
draw.SimpleText(Format("%.1f:%.1f",segm.x,segm.y),"Metrostroi_Arial10",x,y-20,Color(255,0,0),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER)
local mainM = segmM and (dir and segmM.x > segm.x or not dir and segmM.x < segm.x)
local mainP = segmP and (dir and segmP.x > segm.x or not dir and segmP.x < segm.x)
if i==7 and last.next_a then
draw.SimpleText(i,"Metrostroi_Arial20",x,y,Color(0,255,0),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER)
local x,y = GetXY(last.x,last.y)
draw.SimpleText(i-1,"Metrostroi_Arial20",x,y,Color(255,255,0),TEXT_ALIGN_CENTER,TEXT_ALIGN_CENTER)
--print(last.next_a,segm)
end
if segmA and mainM and depth+1 < maxd then
--if i==3 then print(1) end
local xn,yn = GetXY(segmA.x,segmA.y)
surface.SetDrawColor(Color(255,0,0))
surface.DrawLine(x,y,xn,yn)
if findt(station,segmA,dir,i+1,depth+1,segm) then return end
return true
--if i==5 then print("RES",segm.x,segm.y,NextA.x,NextA.y) end
end
if segmM and mainM and depth < maxd then
local xn,yn = GetXY(segmM.x,segmM.y)
surface.SetDrawColor(Color(0,255,0))
surface.DrawLine(x,y,xn,yn)
if findt(station,segmM,dir,i+1,depth,segm) then return end
end
if segmP and mainP and depth < maxd then
local xn,yn = GetXY(segmP.x,segmP.y)
local alt = last and segm.next_a == last or segmP.next_a == segm
if alt then surface.SetDrawColor(Color(255,255,0))
else surface.SetDrawColor(Color(0,255,255)) end
surface.DrawLine(x,y,xn,yn)
if findt(station,segmP,dir,i+1,depth,segm) then return end
end
end
findt(stat,stat[x],dir)
end--]==]
--findt(stat,stat[6],false)
end
Metrostroi.GenerateClientProps()

View File

@@ -0,0 +1,169 @@
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
include("shared.lua")
function ENT:Initialize()
self:SetModel("models/props_combine/breendesk.mdl")
self.BaseClass.Initialize(self)
self.DriverSeat = self:CreateSeat("driver", Vector(-40, 0, 0), Angle(0, 0, 0), "models//nova/chair_office02.mdl")
self.CursorX = 0
self.CursorY = 0
self:CursorMove(0, 0)
self.Station = 0
end
hook.Add("AcceptInput", "metrostroi_arm_trigger_check", function(ent, inputName, activator, called, data)
if inputName == "ARMStartTouch" then
called.ARMTriggered = true
print(called, called:GetName(), activator, "Enable")
end
if inputName == "ARMEndTouch" then
called.ARMTriggered = false
print(called, called:GetName(), activator, "Disable")
end
end)
local function GetOccupation(tbl)
for sID,signame in ipairs(tbl) do
if signame[1] == "@" then
local trigger = Metrostroi.ARMGet(signame:sub(2,-1), "trigger")
if not trigger or trigger.ARMTriggered then
return true
end
elseif signame ~= "" then
local signal = Metrostroi.ARMGet(signame, "signal")
if not signal or signal.OccupiedBy and signal.OccupiedBy ~= signal then
return true
end
end
end
return false
end
function ENT:Think()
local armTbl = Metrostroi.ARMTable
local armConf = Metrostroi.ARMConfigGenerated
local station = armConf[self.Station]
local armTblStation = armTbl[self.Station]
if not station then return end
if not armTblStation or (IsValid(armTblStation.Controller) and armTblStation.Controller ~= self) then return end
armTblStation.Controller = self
for buttonID,button in ipairs(station.buttons) do
--print(button,button.selected)
Metrostroi.ARMSync(self.Station, 1000+buttonID, "buttonPressable",button.pressable)
Metrostroi.ARMSync(self.Station, 1000+buttonID, "buttonSelected",button.selected)
end
for segmID, segm in ipairs(station) do
if type(segm) == "table" then
if segm.occup then
Metrostroi.ARMSync(self.Station, segmID, "occup", GetOccupation(segm.occup) or segm.occupAlt and GetOccupation(segm.occupAlt))
end
if segm.occup2 then
Metrostroi.ARMSync(self.Station, segmID, "occup2", GetOccupation(segm.occup2))
end
Metrostroi.ARMSync(self.Station, segmID, "route", segm.route and true)
if segm.switch then
local switch = Metrostroi.ARMGet(segm.switch, "switch")
local main = switch and switch.MainTrack and not switch.AlternateTrack
local alt = switch and not switch.MainTrack and switch.AlternateTrack
Metrostroi.ARMSync(self.Station, segmID, "switch_m", main)
Metrostroi.ARMSync(self.Station, segmID, "switch_a", alt)
Metrostroi.ARMSync(self.Station, segmID, "switch_na", not main and not alt)
end
if segm.signal1 then
local signal = Metrostroi.ARMGet(segm.signal1.name, "signal")
local colors = signal and signal.Colors
if segm.signal1.type > 1 then Metrostroi.ARMSync(self.Station, segmID, "signal1I", signal and signal.InvationSignal) end
if segm.signal1.type > 2 then
local Y = #colors:gsub("[^yY]","") > 1
if Y then colors = colors:SetChar(colors:find("[yY]"),"") end
Metrostroi.ARMSync(self.Station, segmID, "signal1Y", Y)
end
Metrostroi.ARMSync(self.Station, segmID, "signal1", colors)
end
if segm.signal2 then
local signal = Metrostroi.ARMGet(segm.signal2.name, "signal")
local colors = signal and signal.Colors
if segm.signal2.type > 1 then Metrostroi.ARMSync(self.Station, segmID, "signal2I", signal and signal.InvationSignal) end
if segm.signal2.type > 2 then
local Y = #colors:gsub("[^yY]","") > 1
if Y then colors = colors:SetChar(colors:find("[yY]"),"") end
Metrostroi.ARMSync(self.Station, segmID, "signal2Y", Y)
end
Metrostroi.ARMSync(self.Station, segmID, "signal2", colors)
end
end
end
self:NextThink(CurTime() + 0.5)
return true
end
function ENT:OnRemove()
end
function ENT:CursorMove(sys, dX, dY)
self.CursorX = sys == "" and math.Clamp(self.CursorX + dX * 200, 0, 800) or dX
self.CursorY = sys == "" and math.Clamp(self.CursorY + dY * 200, 0, 600) or dY
self:SetNW2Int("CursorX", math.floor(self.CursorX))
self:SetNW2Int("CursorY", math.floor(self.CursorY))
end
function ENT:PanelTouch(state, x, y)
for i, v in ipairs(Metrostroi.ARMConfig) do
if math.InRangeXYR(self.CursorX, self.CursorY, 20 + (i - 1) * 30, 20, 30, 20) then
self.Station = i
self:SetNW2Int("ARM:Station", i)
end
end
if not state then return end
local RouteChoosing = self.RouteChoosing
self.RouteChoosing = nil
if RouteChoosing then
print("DISABLE")
for k,v in pairs(RouteChoosing.routes) do
if v[1].button then
v[1].button.selected = false
elseif v[1].isbutton then
v[1].selected = false
end
end
end
local confGenStation = Metrostroi.ARMConfigGenerated[self.Station]
for k,button in pairs(confGenStation.buttons) do
local sx,sy = 100+button.x*36,100+button.y*70
if button.type == "r" then
local sw,sh = 15,25
local xa,ya = 3,12
local x,y = sx+xa,sy+ya
if RouteChoosing then
if math.InRangeXYR(self.CursorX, self.CursorY, x,y,sw,sh) then
for k,v in ipairs(RouteChoosing.routes) do
if v[1].button and button == v[1].button or v[1].isbutton and button==v[1] then
Metrostroi.CentralisationPrepareRoute(self.Station,v)
end
end
end
elseif not self.RouteChoosing and button.pressable then
if math.InRangeXYR(self.CursorX, self.CursorY, x,y,sw,sh) then
self.RouteChoosing = button
for k,v in ipairs(button.routes) do
print(v[1],v[1].name,v[1].button)
if v[1].button then
v[1].button.selected = true
elseif v[1].isbutton then
v[1].selected = true
print(2)
end
end
end
end
end
end
end

View File

@@ -0,0 +1,656 @@
ENT.Type = "anim"
--Inherit subway base for some need functions
ENT.Base = "gmod_subway_base"
ENT.NoTrain = true
ENT.PrintNameTranslated = "Entities.ARM"
ENT.Category = "Metrostroi"
ENT.Spawnable = false
ENT.AdminSpawnable = true
ENT.Cameras = {
{Vector(-18+3,0,43+2),Angle(0,0,0),"ARM.Monitor1",true},
}
ENT.Types = {
--Main segments
[0.25]={
maintex = {"metrostroi_arm/sec025",w=8,h=8,rw=7,rh=8,},
occup_m = {"metrostroi_arm/sec025_m",col=Color(255,255,255)},
route_m = {"metrostroi_arm/sec025_m",col=Color(39,103,63)},
width = 0.25,
next_m = {x=0.25,y=0}
},
[0.5]={
maintex = {"metrostroi_arm/sec05",w=16,h=8,rw=16,rh=8,},
occup_m = {"metrostroi_arm/sec05_m",col=Color(255,255,255)},
route_m = {"metrostroi_arm/sec05_m",col=Color(39,103,63)},
width = 0.5,
next_m = {x=0.5,y=0}
},
[1]={
maintex = {"metrostroi_arm/sec1",w=64,h=8,rw=34,rh=8,},
occup_m = {"metrostroi_arm/sec1_m",col=Color(255,255,255)},
route_m = {"metrostroi_arm/sec1_m",col=Color(39,103,63)},
width = 1,
next_m = {x=1,y=0}
},
[2]={
maintex = {"metrostroi_arm/sec2",w=128,h=8,rw=70,rh=8,},
occup_m = {"metrostroi_arm/sec2_m",col=Color(255,255,255)},
route_m = {"metrostroi_arm/sec2_m",col=Color(39,103,63)},
width = 2,
next_m = {x=2,y=0}
},
[3]={
maintex = {"metrostroi_arm/sec3",w=128,h=8,rw=106,rh=8,},
occup_m = {"metrostroi_arm/sec3_m",col=Color(255,255,255)},
route_m = {"metrostroi_arm/sec3_m",col=Color(39,103,63)},
width = 3,
next_m = {x=3,y=0}
},
[4]={
maintex = {"metrostroi_arm/sec4",w=256,h=8,rw=142,rh=8,},
occup_m = {"metrostroi_arm/sec4_m",col=Color(255,255,255)},
route_m = {"metrostroi_arm/sec4_m",col=Color(39,103,63)},
width = 4,
next_m = {x=4,y=0}
},
[5]={
maintex = {"metrostroi_arm/sec5",w=256,h=8,rw=178,rh=8,},
occup_m = {"metrostroi_arm/sec5_m",col=Color(255,255,255)},
route_m = {"metrostroi_arm/sec5_m",col=Color(39,103,63)},
width = 5,
next_m = {x=5,y=0}
},
--Switches and helpers
sw = {
maintex = {"metrostroi_arm/switch",w=128,h=128,rw=70,rh=78,},
occup_m = {"metrostroi_arm/switch_m",col=Color(255,255,255)},
route_m = {"metrostroi_arm/switch_m",col=Color(39,103,63)},
occup_a = {"metrostroi_arm/switch_a",col=Color(255,255,255)},
route_a = {"metrostroi_arm/switch_a",col=Color(39,103,63)},
switch_m = {"metrostroi_arm/switch_ms",col=Color(41,202,26)},
switch_a = {"metrostroi_arm/switch_as",col=Color(240,240,71)},
switch_mn = {"metrostroi_arm/switch_ms",col=Color(200,50,50)},
switch_an = {"metrostroi_arm/switch_as",col=Color(200,50,50)},
width = 2,
next_m = {x=2,y=0},
next_a = {x=2,y=1},
},
["2sw"] = {
maintex = {"metrostroi_arm/2-switch_half",w=128,h=256,rw=70,rh=143,},
occup_m = {"metrostroi_arm/2-switch_half_m",col=Color(255,255,255)},
route_m = {"metrostroi_arm/2-switch_half_m",col=Color(39,103,63)},
occup_a = {"metrostroi_arm/2-switch_half_a",col=Color(255,255,255)},
route_a = {"metrostroi_arm/2-switch_half_a",col=Color(39,103,63)},
switch_m = {"metrostroi_arm/2-switch_half_ms",col=Color(41,202,26)},
switch_a = {"metrostroi_arm/2-switch_half_as",col=Color(240,240,71)},
switch_mn = {"metrostroi_arm/2-switch_half_as",col=Color(200,50,50)},
switch_an = {"metrostroi_arm/2-switch_half_ms",col=Color(200,50,50)},
width = 2,
next_m = {x=2,y=0},
next_a = {x=2,y=2},
},
["2swm"] = {
maintex = {"metrostroi_arm/2-switch-middle_half",w=128,h=128,rw=70,rh=73,},
occup_m = {"metrostroi_arm/2-switch-middle_half_m",col=Color(255,255,255)},
route_m = {"metrostroi_arm/2-switch-middle_half_m",col=Color(39,103,63)},
occup_a = {"metrostroi_arm/2-switch-middle_half_a",col=Color(255,255,255)},
route_a = {"metrostroi_arm/2-switch-middle_half_a",col=Color(39,103,63)},
switch_m = {"metrostroi_arm/2-switch-middle_half_ms",col=Color(41,202,26)},
switch_a = {"metrostroi_arm/2-switch-middle_half_as",col=Color(240,240,71)},
switch_mn = {"metrostroi_arm/2-switch-middle_half_ms",col=Color(200,50,50)},
switch_an = {"metrostroi_arm/2-switch-middle_half_as",col=Color(200,50,50)},
width = 2,
next_m = {x=2,y=0},
next_a = {x=1.5,y=1},
},
["4sw"] = {
maintex = {"metrostroi_arm/4-switch_quarter",w=128,h=256,rw=73,rh=143,x=-3,},
occup_m = {"metrostroi_arm/4-switch_quarter_m",col=Color(255,255,255)},
route_m = {"metrostroi_arm/4-switch_quarter_m",col=Color(39,103,63)},
occup_a = {"metrostroi_arm/4-switch_quarter_a1",col=Color(255,255,255)},
route_a = {"metrostroi_arm/4-switch_quarter_a1",col=Color(39,103,63)},
occup_x = {"metrostroi_arm/4-switch_quarter_a2",col=Color(255,255,255)},
route_x = {"metrostroi_arm/4-switch_quarter_a2",col=Color(39,103,63)},
switch_m = {"metrostroi_arm/4-switch_quarter_ms",col=Color(41,202,26)},
switch_a = {"metrostroi_arm/4-switch_quarter_as",col=Color(240,240,71)},
switch_mn = {"metrostroi_arm/4-switch_quarter_ms",col=Color(200,50,50)},
switch_an = {"metrostroi_arm/4-switch_quarter_as",col=Color(200,50,50)},
width = 2,
next_m = {x=2,y=0},
next_a = {x=2,y=2},
acc_x = ">",
acc_y = "!",
},
["4sws"] = {
maintex = {"metrostroi_arm/4-switch_quarter_small",w=64,h=128,rw=53,rh=78,x=-1,},
occup_m = {"metrostroi_arm/4-switch_quarter_small_m",col=Color(255,255,255),x=-1,},
route_m = {"metrostroi_arm/4-switch_quarter_small_m",col=Color(39,103,63),x=-1,},
occup_a = {"metrostroi_arm/4-switch_quarter_small_a",col=Color(255,255,255),x=-1,},
route_a = {"metrostroi_arm/4-switch_quarter_small_a",col=Color(39,103,63),x=-1,},
switch_m = {"metrostroi_arm/4-switch_quarter_small_ms",col=Color(41,202,26)},
switch_a = {"metrostroi_arm/4-switch_quarter_small_as",col=Color(240,240,71)},
switch_mn = {"metrostroi_arm/4-switch_quarter_small_ms",col=Color(200,50,50)},
switch_an = {"metrostroi_arm/4-switch_quarter_small_as",col=Color(200,50,50)},
width = 1.5,
next_m = {x=1.5,y=0},
next_a = {x=1.5,y=1},
acc_x = ">",
acc_y = "!",
},
ofd = {
maintex = {"metrostroi_arm/offset_down",w=64,h=256,rw=57,rh=143,},
occup_m = {"metrostroi_arm/offset_down_m",col=Color(255,255,255)},
route_m = {"metrostroi_arm/offset_down_m",col=Color(39,103,63)},
width = 2,
next_m = {x=2,y=2},
},
ofds = {
maintex = {"metrostroi_arm/offsed_down_small",w=128,h=128,rw=70,rh=78,},
occup_m = {"metrostroi_arm/offsed_down_small_m",col=Color(255,255,255)},
route_m = {"metrostroi_arm/offsed_down_small_m",col=Color(39,103,63)},
width = 2,
next_m = {x=2,y=1},
},
ysw = {
maintex = {"metrostroi_arm/Y-switch_half",w=128,h=128,rw=70,rh=108,},
occup_m = {"metrostroi_arm/Y-switch_half_m",col=Color(255,255,255)},
route_m = {"metrostroi_arm/Y-switch_half_m",col=Color(39,103,63)},
occup_a = {"metrostroi_arm/Y-switch_half_a",col=Color(255,255,255)},
route_a = {"metrostroi_arm/Y-switch_half_a",col=Color(39,103,63)},
switch_m = {"metrostroi_arm/Y-switch_half_ms",col=Color(41,202,26)},
switch_a = {"metrostroi_arm/Y-switch_half_as",col=Color(240,240,71)},
switch_mn = {"metrostroi_arm/Y-switch_half_ms",col=Color(200,50,50)},
switch_an = {"metrostroi_arm/Y-switch_half_as",col=Color(200,50,50)},
width = 2,
next_m = {x=2,y=0},
next_a = {x=2,y=1},
},
--Signals
tl_1 = {
maintex = {"metrostroi_arm/tl_1",w=32,h=16,rw=21,rh=13},
full = {"metrostroi_arm/tl_f",w=16,h=16,rw=12,rh=12},
h1 = {"metrostroi_arm/tl_h1",w=16,h=16,rw=12,rh=12},
h2 = {"metrostroi_arm/tl_h2",w=16,h=16,rw=12,rh=12},
},
tl_2 = {
maintex = {"metrostroi_arm/tl_2",w=64,h=16,rw=34,rh=13},
full = {"metrostroi_arm/tl_f",w=16,h=16,rw=12,rh=12},
h1 = {"metrostroi_arm/tl_h1",w=16,h=16,rw=12,rh=12},
h2 = {"metrostroi_arm/tl_h2",w=16,h=16,rw=12,rh=12},
},
tl_3 = {
maintex = {"metrostroi_arm/tl_3",w=64,h=16,rw=47,rh=13},
full = {"metrostroi_arm/tl_f",w=16,h=16,rw=12,rh=12},
h1 = {"metrostroi_arm/tl_h1",w=16,h=16,rw=12,rh=12},
h2 = {"metrostroi_arm/tl_h2",w=16,h=16,rw=12,rh=12},
},
}
if CLIENT then
for i,segm in pairs(ENT.Types) do
for k,tex in pairs(segm) do
if type(tex) ~= "table" or type(tex[1]) ~= "string" then continue end
tex.mat = surface.GetTextureID(tex[1])
end
segm.id = i
end
end
--------------
-- Syntax of table
-- {
-- station = "ID,abbreviation,full name"
-- First line of segments
-- {"segment type:occupation checkers,...,occupation checkers:lights:...:lights"},
-- Second line of segments
-- {x=x indent,skip=y indent(skips y segments vertically),"segment type:occupation checkers main,...,occupation checkers main:occupation checkers alt,...,occupation checkers alt:lights:...:lights"},
-- }
-- segment type can have > or ! on start, when we want mirror it vertically or horisontally
-- Occupation checkers can be triggers(have @ in start of trigger name) or signals
-- Lights can be empty, if we want take light name from occupation checkers
-- Lights can have ! when stay in right direction or !! when stay in opposite direction
-- Lights can have > when we want switch light location from bottom to top
-- Examples
--{
-- station = "001,ST,Station name",
-- {
-- {"1:L1:!","1:L3:!","sw:@sw1trigger:@sw3trigger"}
-- {x=1,"1:L2",">sw:@sw2trigger:@sw3rigger"},
-- }
--}
--------------
Metrostroi.ARMConfig = {
{
station = "451,ВБ,Уоллеса брина",
{"0.5:1","0.5:1","0.5:1","0.5:1","1:1","1:1","1:1","sw:1","3:1","3:1"},
{x=7,"0.5:1","4sws:1",">4sws:1","1:1","1:1"},{skip=1},
{x=7,"0.5:1","!4sws:1",">!4sws:1","1:1","1:1"},
{"0.5:1","0.5:1","0.5:1","0.5:1","1:1","1:1","1:1","!sw:1","3:1","3:1"},
},{
station="915,РЧ,Речная",
{x=3.5,"0.5:RX22","1:RX22","1:RX20","0.5:RX98","4sw:::RX1:0",">4sw:::RX3:","1","2","2","1","1"},{skip=3},
{"1:201","0.5:203","0.5:205","0.5:207","0.5:209","0.5:211","0.5:213","1:215","1:217","0.5:219","!4sw:::RX2::!!2RX95",">!4sw:::RX4:","1","2","2","1","1"},
},{
station="110,МД,Международная",
{"1:19:!1","1:17:!1","1:15:!1","1:13:!1","3:11:!>1","sw:@wt_md_s1_1,@wt_md_s1_2:@wt_md_s1_3:MD1:!!>2D:!>2G","5:@wt_md_t1"},
{x=9,"4sws:@wt_md_s3::MD3",">4sws:@wt_md_s5::MD5:!2MD1","2:@wt_md_t3"},{skip=1},
{x=9,"!4sws:@wt_md_s4::MD4",">!4sws:@wt_md_s6::MD6:!>2MD2","2:@wt_md_t4"},
{"1:MD16:!!2","1:MD14:!!2","1:MD12:!!2","1:MD10:!!2:!1 OP","1:MD8:!!2","1:MD8A","1:MD8B","!sw:@wt_md_s2_1,@wt_md_s2_2:@wt_md_s2_3:MD2:!!2MD6:!2E","5:@wt_md_t2"},
buttons = {
{type="r",y=4-0.6 ,x=4, signal=" OP"},
{type="r",y=4 ,x=6+0.4, signal="MD6"},
{type="r",y=4-0.6 ,x=9, signal="E"},
{type="r",y=3 ,x=14, signal="4I",target={12,3}},
{type="r",y=1-0.6 ,x=14, signal="3I",target={12,1}},
{type="r",y=3 ,x=12, signal="MD2"},
{type="r",y=1-0.6 ,x=12, signal="MD1"},
--{type="r",y=0-0.6 ,x=4, signal="13"},
{type="r",y=0-0.6 ,x=6+0.4, signal="D",target={4,0}},
{type="r",y=0 ,x=9, signal="G"},
},
routes = {
MD6={"4I","3I"},
E={" OP"},
MD2={" OP","D"},
MD1={" OP","13"},
D={"4I","3I"},
G={"13"},
}
},{
station="112,ПТ,Политехническая",
{x=1,"1:PT2TB","2:PT2TA","2:PT2T:!!2PT2","2:PT4SA:!!2PT4",">2swm:@wt_pt_s4_1,@wt_pt_s4_2,@wt_pt_s4_3::PT4:!3PT968M:!!2G ","1:PT966A","2:PT966:!>2","sw:@wt_pt_s6_2,@wt_pt_s6_3::PT6:!>2PT964:!!>3A","1:962"},
{x=15,"1:PT6SS","1:963"},
{x=1,"1:77:!1","1:75:!1","1:73:!1","1:71:!>1",">2swm:@wt_pt_s1_1::PT1:!!>2B","!2swm:@wt_pt_s3_1:@wt_pt_s3_2:PT3:!>2PT69","1:PT67M:!2","1:PT65B","1:PT65A","1:PT65:!2","1:PT63:!2:!!1 OP ","1:PT61:!2","1:PT59:!2","1:PT57:!2"},{skip=1},
{"1:PT70:!!2:!1 OP2 ","1:PT68:!!2","2:@wt_pt_s2_3:!!2PT66","!2swm:@wt_pt_s2_1:@wt_pt_s2_2:PT2:!!3PT64","2","2:62:!!1","1:60:!!1","2:60A","1:58M:!!1","1:56:!!1","1:54:!!1","1: 52:!!1"},
{},
labels = {
},
buttons = {
{type="r",y=0-0.6 ,x=1, signal="3T",target={1,0},flip=true},
{type="r",y=0 ,x=3+0.4,signal="PT2",target={1,0},flip=true},
{type="r",y=4-0.6 ,x=1, signal=" OP2 "},
{type="r",y=4 ,x=-1+0.4, signal="PT70"},
{type="r",y=4 ,x=3+0.4, signal="2P",target={6,4}},
--{type="r",y=4 ,x=7+0.4, signal="62"},
{type="r",y=2 ,x=5, signal="71"},
{type="r",y=2-0.6 ,x=4+0.4, signal="B",target={5,2}},
{type="r",y=2-0.6 ,x=17, signal="PT57"},
{type="r",y=2-0.6 ,x=10, signal="PT67M"},
{type="r",y=2 ,x=12+0.4,signal=" OP "},
{type="r",y=0-0.6 ,x=10, signal="PT968M",flip=true},
{type="r",y=0 ,x=15, signal="PT964",flip=true},
{type="r",y=1-0.6 ,x=15, signal="4O",target={15,1},flip=true},
{type="r",y=0-0.6 ,x=12+0.4,signal="A",flip=true},
},
routes = {
PT2 = {"A"},
PT70 = {" OP ","A","2P"},
--PT64 = {" OP ","A","PT64"},
B = {" OP ","A"},
PT57 = {"PT67M"},
PT964 = {"PT968M"},
PT67M = {"71"," OP2 "},
PT968M = {"3T","71"," OP2 "},
A={"4O"}
}
},{
station="115,ОК,Октябрьская",
{"1","1","1","1","3","sw:::OK1","1"},
{x=9,"4sws:::OK3",">4sws:::OK5","1"},{skip=1},
{x=9,"!4sws:::OK4",">!4sws:::OK6","1"},
{"1","1","1","1","3","!sw:::OK2","5"},
}
}
print("MetrostroiARM:Generating ARM table...")
local errors,warnings = 0,0
local function ARMGenError(text,err)
MsgC(Color(255,err and 0 or 255,0),"MetrostroiARM:"..text.."\n")
ErrorNoHalt()
if err then errors = errors + 1 else warnings = warnings + 1 end
end
local function ParseARMTable(text,station,line,segm)
local resultTbl = {}
local tbl = string.Explode(":",text)
local typ = tbl[1]
if typ:find("^[>!]") then
resultTbl.invertX = typ:find(">")
resultTbl.invertY = typ:find("!")
typ = typ:gsub("^[>!]+","")
end
local segmTyp = ENT.Types[tonumber(typ) or typ]
if not segmTyp then return {error = 1,type = tbl[1]} end
table.remove(tbl,1)
for i,str in ipairs(tbl) do
if str:find(",") then
tbl[i] = string.Explode(",",str)
end
if str:sub(1,2) == "!!" then
resultTbl.signal2 = str:sub(3,-1)
elseif str[1] == "!" then
resultTbl.signal1 = str:sub(2,-1)
end
end
resultTbl.occup = type(tbl[1]) == "table" and tbl[1] or {tbl[1]}
if segmTyp.occup_a then
resultTbl.occupAlt = type(tbl[2]) == "table" and tbl[2] or {tbl[2]}
resultTbl.switch = tbl[3]
if segmTyp.occup_x then
resultTbl.occup2 = type(tbl[4]) == "table" and tbl[4] or {tbl[4]}
end
end
if resultTbl.signal1 then
local signal = resultTbl.signal1:gsub("^[>]+","")
local top = resultTbl.signal1:find("^>")
local typ = tonumber(signal[1])
local name = signal:sub(2,-1)
if not typ then
ARMGenError(Format("Parser warning. Signal type in id station %d line %d segm %d segment not found. Using default 1",station,line,segm),false)
name = signal[1]..name
elseif typ < 1 or typ > 3 then
ARMGenError(Format("Parser warning. Signal type in id station %d line %d segm %d segment have wrong ID, must be in range 1..3. Using default 1",station,line,segm),false)
typ = 1
end
if name == "" then name = resultTbl.occup[1] end
resultTbl.signal1 = {name=name,type=typ or 1,top = top,segm=resultTbl}
end
if resultTbl.signal2 then
local signal = resultTbl.signal2:gsub("^[>]+","")
local top = resultTbl.signal2:find("^>")
local typ = tonumber(signal[1])
local name = signal:sub(2,-1)
if not typ then
ARMGenError(Format("Parser warning. Signal type in id station %d line %d segm %d segment not found. Using default 1",station,line,segm),false)
name = signal[1]..name
elseif typ < 1 or typ > 3 then
ARMGenError(Format("Parser warning. Signal type in id station %d line %d segm %d segment have wrong ID, must be in range 1..3. Using default 1",station,line,segm),false)
typ = 1
end
if name == "" then name = resultTbl.occup[1] end
resultTbl.signal2 = {name=name,type=typ or 1,top = top,segm=resultTbl}
end
resultTbl.type = typ
resultTbl.width = segmTyp.width or 1
resultTbl.segm = segmTyp
return resultTbl
end
Metrostroi.ARMConfigGenerated = {}
local id = 0
for i,station in ipairs(Metrostroi.ARMConfig) do
if not Metrostroi.ARMConfigGenerated[i] then Metrostroi.ARMConfigGenerated[i] = {} end
local genStation = Metrostroi.ARMConfigGenerated[i]
local y = 0
MsgC(Color(0, 222, 255),"MetrostroiARM:Solving station ",i,"\n")
if #station == 0 then ARMGenError(Format("Parser warning. Empty station %d! Skipping...",i),false) continue end
if not station.station then ARMGenError(Format("Parser error. Can't find station name in station %d! Skipping...",i),true) continue end
local stationTbl = string.Explode(",",station.station)
if not stationTbl or #stationTbl < 3 or not tonumber(stationTbl[1]) then ARMGenError(Format("Parser error. Malformed station data in station %d! Skipping...",i),true) continue end
genStation.id = stationTbl[1]
genStation.shortname = stationTbl[2]
genStation.name = stationTbl[3]
genStation.buttons = {}
genStation.routes = station.routes or {}
for lineID,line in ipairs(station) do
local x = line.x or 0
for segmID,segm in ipairs(line) do
if type(segm) ~= "string" then
ARMGenError(Format("Parser error on station %d line %d segm %d, excepted string,got %s. Skipping segment...",i,lineID,segmID,type(segm)),true)
continue
end
local segmTbl= ParseARMTable(segm,i,lineID,segmID)
if segmTbl.error then
ARMGenError(Format("Parser warning. Skipping station %d line %d segm %d segment, type error(type '%s' not found)",i,lineID,segmID,segmTbl.type),false)
continue
end
segmTbl.x = x
segmTbl.y = y
segmTbl.id = table.insert(genStation,segmTbl)
x = x + (segmTbl.width or 1)
end
y = y + (line.skip or 1)
end
if station.buttons then
for _,button in pairs(station.buttons) do
button.pressable = false
button.selected = false
button.isbutton = true
if button.type == "r" then
button.segm = ENT.Types.button_normal
for k,v in ipairs(genStation) do
if v.signal1 and v.signal1.name == button.signal then
button.segm = v
v.signal1.button = button
break
end
if v.signal2 and v.signal2.name == button.signal then
button.segm = v
v.signal2.button = button
break
end
if button.target and button.target[1] == v.x and button.target[2] == v.y then
button.segm = v
v.button = button
if v.button then
v.button = nil
v.buttons = {v.button,button}
end
break
end
end
end
table.insert(genStation.buttons,button)
end
end
end
local function GetXY(x,y)
return 100+x*36,100+y*70
end
local function GetSegmPos(segm,alt)
local x,y = segm.x,segm.y
local segmt = segm.segm
local u0,v0,u1,v1 = 0,0,1,1
if segm.invertX then u0,u1 = 1,0 end
if segm.invertY then v0,v1 = 1,0 end
if alt == nil then
return GetXY(x+segm.width*u0,y)
elseif alt == false and segmt.next_m then
return GetXY(x+segmt.next_m.x-segm.width*u0,y+segmt.next_m.y)
--print(123,x,y)
elseif alt and segmt.next_a then
return GetXY(x+segmt.next_a.x*u1-segmt.next_a.x*u0+segmt.width*u0,y+segmt.next_a.y*v1-segmt.next_a.y*v0)
end
end
local function ARMSetNextCompare(posX,posY,segm,nsegm)
local xp,yp = GetSegmPos(segm)
local x,y = GetSegmPos(nsegm)
if sx and posX == x and posY == y then
nsegm.prev = segm
return true
end
sx,sy = GetSegmPos(nsegm,false)
if sx and posX == sx and posY == sy then
nsegm.next_m = segm
return true
end
if not nsegm.segm.next_a then return end
sx,sy = GetSegmPos(nsegm,true)
if x ~= xp and y ~= yp and sx and posX == sx and posY == sy then
nsegm.next_a = segm
if segm.id == 29 then
local x1,y1 = GetSegmPos(nsegm)
local x2,y2 = GetSegmPos(segm)
print(-2,x1,y1,x2,y2)
end
return true
end
end
local function ARMSetNext(station)
for csegmid,csegm in ipairs(station) do
for segmid,segm in ipairs(station) do
if segm == csegm then continue end
local posX,posY = GetSegmPos(csegm)
if ARMSetNextCompare(posX,posY,csegm,segm) then
csegm.prev = segm
--break
end
local posOX,posOY = GetSegmPos(csegm,false)
if ARMSetNextCompare(posOX,posOY,csegm,segm) then
csegm.next_m = segm
--break
end
local posAX,posAY = GetSegmPos(segm)
if not csegm.segm.next_a or posX == posAX or posY == posAY then continue end
posOX,posOY = GetSegmPos(csegm,true)
if ARMSetNextCompare(posOX,posOY,csegm,segm) then
csegm.next_a = segm
--break
end
end
end
end
for i,st in ipairs(Metrostroi.ARMConfigGenerated) do ARMSetNext(st) end
local function tcopy(from)
local t = {}
for k,v in pairs(from) do
t[k] = v
end
return t
end
local iter = 1
local function ARMFindSegmSignals(station,segm,dir,signals,last,checked,restbl,trace)
if not restbl then restbl = {} end
if not checked then checked = {} end
if not trace then trace = {} end
if checked[segm] then return end
checked[segm] = true
local segmIndex = table.insert(trace,{segm.id})
--trace[segm] = true
iter = iter + 1
if iter > 10000 then ARMGenError(Format("Routes generation error. Max iter reached!"),true) return false end
local segmM,segmA = segm.next_m,segm.next_a
local segmP = segm.prev
local mainM = segmM and (dir and segmM.x > segm.x or not dir and segmM.x < segm.x)
local mainP = segmP and (dir and segmP.x > segm.x or not dir and segmP.x < segm.x)
if segmA and mainM then
local trace= table.Copy(trace)
trace[segmIndex][2] = true
local signal = dir and segmA.signal2 or segmA.signal1
local button = segmA.button
if signal and table.HasValue(signals,signal.name) then
table.insert(restbl,{signal,table.Copy(trace)})
elseif button and table.HasValue(signals,button.signal) then
table.insert(trace,{segmA.id})
table.insert(restbl,{button,table.Copy(trace)})
end
ARMFindSegmSignals(station,segmA,dir,signals,segm,checked,restbl,trace)
end
if segmM and mainM then
local signal = dir and segmM.signal2 or segmM.signal1
local button = segmM.button
if signal and table.HasValue(signals,signal.name) then
table.insert(restbl,{signal,table.Copy(trace)})
elseif button and table.HasValue(signals,button.signal) then
table.insert(trace,{segmM.id})
table.insert(restbl,{button,table.Copy(trace)})
end
ARMFindSegmSignals(station,segmM,dir,signals,segm,checked,restbl,trace)
end
if segmP and mainP then
trace[segmIndex][2] = last and segm.next_a == last or nil-- or segmP.next_a == segm or nil
local signal = dir and segmP.signal2 or segmP.signal1
local button = segmP.button
if signal and table.HasValue(signals,signal.name) then
table.insert(restbl,{signal,table.Copy(trace)})
elseif button and table.HasValue(signals,button.signal) then
table.insert(trace,{segmP.id})
table.insert(restbl,{button,table.Copy(trace)})
end
ARMFindSegmSignals(station,segmP,dir,signals,segm,checked,restbl,trace)
end
return restbl
end
for i,station in ipairs(Metrostroi.ARMConfigGenerated) do
print("STATION",i)
for _,button in pairs(station.buttons) do
if button.type == "r" and station.routes[button.signal] then
print(button.signal,button.segm)
button.pressable = true
local results = ARMFindSegmSignals(station,button.segm,false,station.routes[button.signal])
if #results == 0 then
results = ARMFindSegmSignals(station,button.segm,true,station.routes[button.signal])
end
for k,v in pairs(results) do
local i = 0
for k,v in pairs(v[2]) do i = i + 1 end
print("--",k,v,v[1],v[2],i)
end
--print(results[1][1].name,results[1][1].segm)--]]
button.routes = results
end
--[[ if segm.signal2 then
local result = ARMFindNextSegm(station,segm,true,nil,nil,segm.signal2.name=="PT640")
if result and #result > 0 then
print(segm.signal2.name.."->")
for k,v in ipairs(result) do print(" "..v.name) end
end
end
if segm.signal1 then
local result = ARMFindNextSegm(station,segm,false,nil,nil,segm.signal1.name=="MD01")
if result and #result > 0 then
print(segm.signal1.name.."->")
for k,v in ipairs(result) do print(" "..v.name) end
end
end--]]
end
end
if errors == 0 and warnings == 0 then
MsgC(Color(0,255,0),"MetrostroiARM:Generate finished without errors and warnings.\n")
elseif errors == 0 then
MsgC(Color(255,255,0),"MetrostroiARM:Generate finished with "..warnings.." warnings.\n")
else
MsgC(Color(255,0,0),"MetrostroiARM:Generate finished with "..errors.." errors and "..warnings.." warnings!\n")
end
--PrintTable(Metrostroi.ARMConfigGenerated)
for k,v in ipairs(Metrostroi.ARMConfigGenerated) do
Metrostroi.ARMTable[k] = {
occChecks = {},
net = {},
signal = {},
switch = {},
routes = {},
}
end