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 local idx = add and v..add or v if IsValid(self.Models[1][idx]) then break else local k_long = k.."_long" if TLM[k_long] and LenseNum >= 7 then self.Models[1][idx] = ClientsideModel(TLM[k_long],RENDERGROUP_OPAQUE) self.LongOffset = Vector(0,0,TLM[k.."_long_pos"]) else self.Models[1][idx] = ClientsideModel(v,RENDERGROUP_OPAQUE) end self.Models[1][idx]:SetPos(self:LocalToWorld(pos)) self.Models[1][idx]:SetAngles(self:LocalToWorldAngles(ang)) self.Models[1][idx]: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 local rouid = id and "rou"..id if rouid and not IsValid(self.Models[1][rouid]) 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") local LampIndicator = self.TrafficLightModels[self.LightType].LampIndicator self.Models[1][rouid] = ClientsideModel(LampIndicator.model..rnadd..".mdl",RENDERGROUP_OPAQUE) self.Models[1][rouid]:SetPos(self:LocalToWorld(pos-self.RouteNumberOffset*(self.Left and LampIndicator[1] or LampIndicator[2]))) self.Models[1][rouid]:SetAngles(self:GetAngles()) self.Models[1][rouid]:SetParent(self) if self.RouteNumbers[id] then self.RouteNumbers[id].pos = pos-self.RouteNumberOffset*(self.Left and LampIndicator[1] or LampIndicator[2]) end self.RN = self.RN + 1 end if notM then if glass then local ID_glass = tostring(ID).."_glass" for i,tbl in pairs(glass) do local ID_glassi = ID_glass..i if not IsValid(self.Models[1][ID_glassi]) then --NEWLENSES self.Models[1][ID_glassi] = ClientsideModel(tbl[1],RENDERGROUP_OPAQUE) self.Models[1][ID_glassi]:SetPos(self:LocalToWorld(pos+tbl[2]*(add and Vector(-1,1,1) or 1))) self.Models[1][ID_glassi]:SetAngles(self:LocalToWorldAngles(ang)) self.Models[1][ID_glassi]:SetParent(self) end end end end end function ENT:SetLight(ID,ID2,pos,ang,skin,State,Change) local IsStateAboveZero = State > 0 local IDID2 = ID..ID2 local IsModelValid = IsValid(self.Models[3][IDID2]) if IsModelValid then if IsStateAboveZero then if Change then self.Models[3][IDID2]:SetColor(Color(255,255,255,State*255)) end else self.Models[3][IDID2]:Remove() end elseif IsStateAboveZero then self.Models[3][IDID2] = ClientsideModel(self.TrafficLightModels[self.LightType].LampBase.model,RENDERGROUP_OPAQUE) self.Models[3][IDID2]:SetPos(self:LocalToWorld(pos)) self.Models[3][IDID2]:SetAngles(self:LocalToWorldAngles(ang)) self.Models[3][IDID2]:SetSkin(skin) self.Models[3][IDID2]:SetParent(self) self.Models[3][IDID2]:SetRenderMode(RENDERMODE_TRANSCOLOR) -- self.Models[3][IDID2]:SetColor(Color(255, 255, 255, 0)) self.Models[3][IDID2]:SetColor(Color(255,255,255,State*255)) end end function ENT:SpawnLetter(i,model,pos,letter,double) local LetMaterials = self.TrafficLightModels[self.LightType].LetMaterials.str local LetMaterialsStart = LetMaterials.."let_start" local LetMaterialsletter = LetMaterials..letter 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(LetMaterialsStart) then self.Models[2][i]:SetSubMaterial(k-1,LetMaterialsletter) end end end local id = i.."d" if not double and not IsValid(self.Models[2][id]) 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][id] = ClientsideModel(model,RENDERGROUP_OPAQUE) self.Models[2][id]:SetAngles(self:LocalToWorldAngles(Angle(0,180,0))) self.Models[2][id]:SetPos(self:LocalToWorld((self.BasePosition+pos)*Vector(-1,1,1))) self.Models[2][id]:SetParent(self) for k,v in pairs(self.Models[2][id]:GetMaterials()) do if v:find(LetMaterialsStart) then self.Models[2][id]:SetSubMaterial(k-1,LetMaterialsletter) 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) local C_RenderDistance = GetConVar("metrostroi_distance_signal") local C_ScreenshotMode = GetConVar("metrostroi_screenshotmode") local timer = CurTime() hook.Add("Think","MetrostroiRenderSignals", function() if CurTime() - timer < 1.5 or not IsValid(LocalPlayer()) or C_ScreenshotMode:GetBool() then return end timer = CurTime() local plyPos = LocalPlayer():GetPos() local dist = C_RenderDistance:GetInt()/0.01905 for _,sig in pairs(ents.FindByClass("gmod_track_signal")) do if not IsValid(sig) then continue end local sigPos = sig:GetPos() sig.RenderDisable = sigPos:Distance(plyPos) > dist or math.abs(plyPos.z - sigPos.z) > 1500 end end) function ENT:Think() local CurTime = CurTime() self:SetNextClientThink(CurTime + 0.0333) self.PrevTime = self.PrevTime or RealTime() self.DeltaTime = (RealTime() - self.PrevTime) self.PrevTime = RealTime() if (self:IsDormant() or Metrostroi and Metrostroi.ReloadClientside or self.RenderDisable and not C_ScreenshotMode:GetBool()) and not self.ReloadModels then if self.ModelsCreated then self:RemoveModels() end return true 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 true 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 --оператор # съедает больше производительности, чем исопльзование своей переменной с хранением количества элементов в таблице --поэтому добавляю каунтеры --TODO вообще сравнить бы это здесь xD local rn1 = {} local rn1N = 0 local rn2 = {} self.RouteNumbers = {} self.SpecRouteNumbers = {} for i=1,#self.RouteNumberSetup do local CurRN = self.RouteNumberSetup[i] if self.OldRouteNumberSetup[1]:find(CurRN) then rn1N = 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,rn1N,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 for k,v in pairs(self.SpecRouteNumbers) do if not v[2] then self.Arrow = k self.SpecRouteNumbers = v break 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(TLM.LampIndicator.model..rnadd..".mdl",RENDERGROUP_OPAQUE) self.RouteNumbers[id].pos = (self.BasePosition+offset+self.LongOffset-TLM.LampIndicator[3]) if self.Left then self.RouteNumbers[id].pos = self.RouteNumbers[id].pos*TLM.LampIndicator[4] 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 = TLM.RouteNumberOffset offset = offset + self.RouteNumberOffset*(self.Left and Vector(-1,1,1) or 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 local vec = Vector(0,0,data[1]) if first then first = false else offset = offset - vec end self.NamesOffset = self.NamesOffset + vec local offsetAndLongOffset = offset + self.LongOffset if not self.Left or self.Double then self:SpawnHeads(ID,data[2],self.BasePosition + offsetAndLongOffset,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) + offsetAndLongOffset,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*(self.Left and Vector(-1,1,1) or 1) + offsetAndLongOffset + data[3][i-1]*(self.Left and Vector(-1,1,1) or 1),Angle(0, 0, 0),self.SignalConverter[v[i]]-1,0 ) else self:SetLight(ID,ID2,self.BasePosition + offsetAndLongOffset + data[3][i-1],Angle(0, 0, 0),self.SignalConverter[v[i]]-1,0) self:SetLight(ID,ID2.."x",self.BasePosition*Vector(-1,1,1) + offsetAndLongOffset + 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(TLM.LampIndicator.model.."4.mdl",RENDERGROUP_OPAQUE) self.SpecRouteNumbers.pos = (self.BasePosition+offset+self.LongOffset-TLM.LampIndicator[5])*(self.Left and TLM.LampIndicator[6] or 1) - (self.RouteNumberOffset or Vector(0, 0, 0)) self.Models[1]["roua"]:SetPos(self:LocalToWorld(self.SpecRouteNumbers.pos)) self.Models[1]["roua"]:SetAngles(self:LocalToWorldAngles(self.Left and Angle(-90,0,0) or Angle(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(0, 0, 0)) 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,TLM.SignLetterSmall.model,offset - TLM.SignLetterSmall[2],(Metrostroi.LiterWarper[self.Name[0+1]] or self.Name[0+1]),true) self:SpawnLetter(1,TLM.SignLetterSmall.model,offset - TLM.SignLetterSmall[1],(Metrostroi.LiterWarper[self.Name[1+1]] or self.Name[1+1]),true) end if self.Left or self.Double then self:SpawnLetter(0,TLM.SignLetterSmall.model,offset - TLM.SignLetterSmall[1],(Metrostroi.LiterWarper[self.Name[0+1]] or self.Name[0+1]),false) self:SpawnLetter(1,TLM.SignLetterSmall.model,offset - TLM.SignLetterSmall[2],(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 + TLM.DoubleOffset 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,TLM.SignLetter.model,offset - Vector(0,0,id*TLM.SignLetter.z),(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,TLM.SignLetter.model,offset - Vector(0,0,id*TLM.SignLetter.z),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*(self.Left and Vector(-1,1,1) or 1))) self.Models[1][k]:SetAngles(self:LocalToWorldAngles(self.Left and Angle(-1,1,1) or Angle(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 true end local offset = (self.RenderOffset[self.LightType] or Vector(0, 0, 0)) if self.RouteNumberOffset then offset = offset + self.RouteNumberOffset*(self.Left and Vector(-1,1) or Vector(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 local n = tonumber(self.Sig[ID2]) if n and self.Signals[ID2].RealState ~= (n > 0) then self.Signals[ID2].RealState = n > 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, ((n == 1 or (n == 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 local offsetAndLongOffset = offset + self.LongOffset if not self.DoubleL then self:SetLight(ID,ID2,self.BasePosition*(self.Left and Vector(-1,1,1) or 1) + offsetAndLongOffset + data[3][i-1]*(self.Left and Vector(-1,1,1) or 1),Angle(0, 0, 0),self.SignalConverter[v[i]]-1,State,self.Signals[ID2].State ~= State) else self:SetLight(ID,ID2,self.BasePosition + offsetAndLongOffset + data[3][i-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) + offsetAndLongOffset + 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 local LampIndicatorModels_numb_mdl = TLM.LampIndicator.model.."_numb.mdl" local LampIndicatorModels_lamp_mdl = TLM.LampIndicator.model.."_lamp.mdl" for k,v in pairs(self.RouteNumbers) do if k == "sep" then continue end local rou1k = "rou1"..k local State1 = self:Animate(rou1k,self.Num:find(v[1]) and 1 or 0, 0,1, 256) local State2 --if v[3] then local rou2k = "rou2"..k if v[2] then State2 = self:Animate(rou2k,self.Num:find(v[2])and 1 or 0, 0,1, 256) end if not IsValid(self.Models[3][rou1k]) and State1 > 0 then self.Models[3][rou1k] = ClientsideModel(v[3] and LampIndicatorModels_numb_mdl or LampIndicatorModels_lamp_mdl,RENDERGROUP_OPAQUE) self.Models[3][rou1k]:SetPos(self:LocalToWorld(v.pos + self.OldRouteNumberSetup[4])) self.Models[3][rou1k]:SetAngles(self:GetAngles()) self.Models[3][rou1k]:SetParent(self) self.Models[3][rou1k]:SetSkin(v[3] and self.OldRouteNumberSetup[5][v[1]] or self.OldRouteNumberSetup[6][v[1]] or tonumber(v[1])-1) self.Models[3][rou1k]:SetRenderMode(RENDERMODE_TRANSCOLOR) self.Models[3][rou1k]:SetColor(Color(255, 255, 255, 0)) end if IsValid(self.Models[3][rou1k]) then if State1 > 0 then self.Models[3][rou1k]:SetColor(Color(255,255,255,State1*255)) elseif State1 == 0 then self.Models[3][rou1k]:Remove() end end if not IsValid(self.Models[3][rou2k]) and v[3] and v[2] and State2 > 0 then self.Models[3][rou2k] = ClientsideModel(LampIndicatorModels_numb_mdl,RENDERGROUP_OPAQUE) self.Models[3][rou2k]:SetPos(self:LocalToWorld(v.pos + self.OldRouteNumberSetup[4] + TLM.RouteNumberOffset2)) self.Models[3][rou2k]:SetAngles(self:GetAngles()) self.Models[3][rou2k]:SetParent(self) self.Models[3][rou2k]:SetSkin(self.OldRouteNumberSetup[5][v[2]] or tonumber(v[2])-1) self.Models[3][rou2k]:SetRenderMode(RENDERMODE_TRANSCOLOR) self.Models[3][rou2k]:SetColor(Color(255, 255, 255, 0)) end if IsValid(self.Models[3][rou2k]) then if State2 > 0 then self.Models[3][rou2k]:SetColor(Color(255,255,255,State2*255)) elseif State2 == 0 then self.Models[3][rou2k]: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(LampIndicatorModels_lamp_mdl,RENDERGROUP_OPAQUE) self.SpecRouteNumbers.pos = (self.BasePosition+offset-TLM.SpecRouteNumberOffset)-(self.RouteNumberOffset or Vector(0, 0, 0))+TLM.RouteNumberOffset3 if self.Left then self.SpecRouteNumbers.pos = self.SpecRouteNumbers.pos*TLM.SpecRouteNumberOffset2 end self.Models[3]["roua"]:SetPos(self.Models[1]["roua"]:LocalToWorld(TLM.RouaOffset)) 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 return true end local C_SignalDebug = GetConVar("metrostroi_drawsignaldebug") function ENT:Draw(flags) -- Draw model self:DrawModel(flags) if not C_SignalDebug:GetBool() then return end if LocalPlayer():GetPos():DistToSqr(self:GetPos()) > 200000 then return end if EyeVector():Dot(self:LocalToWorldAngles(Angle(0,90,90)):Forward()) > 0.1 then return end local pos = self:LocalToWorld(Vector(48,0,150)) local ang = self:LocalToWorldAngles(Angle(0,180,90)) cam.Start3D2D(pos, ang, 0.25) self:DrawDebug() cam.End3D2D() end 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 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), } function ENT:DrawDebug() surface.SetDrawColor(self.ARSOnly and 255 or 125, 125, 0, 255) if not self:GetNW2Bool("Debug",false) then surface.DrawRect(0, 0, 364, 25) draw.DrawText("Debug disabled...","Trebuchet24",5,0,Color(0, 0, 0, 255)) return end if not self.Name then surface.DrawRect(0, 0, 364, 25) draw.DrawText("No data...","Trebuchet24",5,0,Color(0, 0, 0, 255)) return end surface.DrawRect(0, -60, 364, 210) if not self.ARSOnly then surface.DrawRect(0, 155, 240, 165) surface.DrawRect(0, 325, 240, 190) surface.SetDrawColor(0,0,0, 255) surface.DrawRect(245, 155, 119, 365) else surface.DrawRect(0, 155, 364, 165) surface.DrawRect(0, 325, 364, 190) end draw.DrawText(Format("Joint main info (%d)",self:EntIndex()),"Trebuchet24",5,-60,Color(200,0,0,255)) draw.DrawText("Signal name: "..self.Name,"Trebuchet24", 5, -40,Color(0, 0, 0, 255)) draw.DrawText("TrackID: "..self:GetNW2Int("PosID",0),"Trebuchet24", 25, -20,Color(0, 0, 0, 255)) draw.DrawText(Format("PosX: %.02f",self:GetNW2Float("Pos",0)),"Trebuchet24", 135, -20,Color(0, 0, 0, 255)) draw.DrawText(Format("NextSignalName: %s",self:GetNW2String("NextSignalName","N/A")),"Trebuchet24", 5, 0,Color(0, 0, 0, 255)) draw.DrawText(Format("TrackID: %s",self:GetNW2Int("NextPosID",0)),"Trebuchet24", 25, 20,Color(0, 0, 0, 255)) draw.DrawText(Format("PosX: %.02f",self:GetNW2Float("NextPos",0)),"Trebuchet24", 135, 20,Color(0, 0, 0, 255)) draw.DrawText(Format("Dist: %.02f",self:GetNW2Float("DistanceToNext",0)),"Trebuchet24", 5, 40,Color(0, 0, 0, 255)) draw.DrawText(Format("PrevSignalName: %s",self:GetNW2String("PrevSignalName","N/A")),"Trebuchet24", 5, 60,Color(0, 0, 0, 255)) draw.DrawText(Format("TrackID: %s",self:GetNW2Int("PrevPosID",0)),"Trebuchet24", 25, 80,Color(0, 0, 0, 255)) draw.DrawText(Format("PosX: %.02f",self:GetNW2Float("PrevPos",0)),"Trebuchet24", 135, 80,Color(0, 0, 0, 255)) draw.DrawText(Format("DistPrev: %.02f",self:GetNW2Float("DistanceToPrev",0)),"Trebuchet24", 5, 100,Color(0, 0, 0, 255)) draw.DrawText(Format("Current route: %d",self:GetNW2Int("CurrentRoute",-1)),"Trebuchet24", 5, 120,Color(0, 0, 0, 255)) draw.DrawText("AB info","Trebuchet24",5,155,Color(200,0,0,255)) draw.DrawText(Format("Occupied: %s",self:GetNW2Bool("Occupied",false) and "Y" or "N"),"Trebuchet24",5,175,Color(0, 0, 0, 255)) draw.DrawText(Format("Linked to controller: %s",self:GetNW2Bool("LinkedToController",false) and "Y" or "N"),"Trebuchet24",5,195,Color(0, 0, 0, 255)) draw.DrawText(Format("Num: %d",self:GetNW2Int("ControllersNumber",0)),"Trebuchet24",25,215,Color(0, 0, 0, 255)) draw.DrawText(Format("Controller logic: %s",self:GetNW2Bool("BlockedByController",false) and "Y" or "N"),"Trebuchet24",5,235,Color(0, 0, 0, 255)) draw.DrawText(Format("Autostop: %s",not self.ARSOnly and self.AutostopPresent and (self:GetNW2Bool("Autostop") and "Up" or "Down") or "No present"),"Trebuchet24",5,255,Color(0, 0, 0, 255)) draw.DrawText(Format("2/6: %s",self:GetNW2Bool("2/6",false) and "Y" or "N"),"Trebuchet24",5,275,Color(0, 0, 0, 255)) draw.DrawText(Format("FreeBS: %d",self:GetNW2Int("FreeBS")),"Trebuchet24",5,295,Color(0, 0, 0, 255)) draw.DrawText("ARS info","Trebuchet24",5,325,Color(200,0,0,255)) local num = 0 for i,tbl in pairs(ars) do if not tbl then continue end if self:GetNW2Bool("CurrentARS"..(i-1),false) then draw.DrawText(Format("(% s)",tbl[1]),"Trebuchet24",5,345+num*20,Color(0,100,0,255)) draw.DrawText(Format("%s",tbl[2]),"Trebuchet24",105,345+num*20,Color(0,100,0,255)) else draw.DrawText(Format("(% s)",tbl[1]),"Trebuchet24",5,345+num*20,Color(0, 0, 0, 255)) draw.DrawText(Format("%s",tbl[2]),"Trebuchet24",105,345+num*20,Color(0, 0, 0, 255)) end num = num+1 end if self:GetNW2Bool("CurrentARS325",false) or self:GetNW2Bool("CurrentARS325_2",false) then draw.DrawText("(325 Hz)","Trebuchet24",5,345+num*20,Color(0,100,0,255)) draw.DrawText(Format("LN:%s Apr0:%s",self:GetNW2Bool("CurrentARS325",false) and "Y" or "N",self:GetNW2Bool("CurrentARS325_2",false) and "Y" or "N"),"Trebuchet24",105,345+num*20,Color(0,100,0,255)) else draw.DrawText("(325 Hz)","Trebuchet24",5,345+num*20,Color(0, 0, 0, 255)) draw.DrawText(Format("LN:%s Apr0:%s",self:GetNW2Bool("CurrentARS325",false) and "Y" or "N",self:GetNW2Bool("CurrentARS325_2",false) and "Y" or "N"),"Trebuchet24",105,345+num*20,Color(0, 0, 0, 255)) end if not self.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(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 --self.NamesOffset = self.NamesOffset + Vector(0,0,data[1]) if v ~= "M" then for i = 1,#v do ID2 = ID2 + 1 local n = tonumber(self.Sig[ID2]) local State = n == 1 and "X" or (n == 2 and (RealTime() % 1.2 > 0.4)) and "B" or false draw.DrawText(Format(v[i],self: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(self.Num or "none","Trebuchet24",280,160 + ID*20 + ID2*20,Color(200,200,200)) --if Metrostroi.RoutePointer[self.Num[1]] then self.Models[1][self.RouteNumber]:SetSkin(Metrostroi.RoutePointer[self.Num[1]]) end end ID = ID + 1 end end end Metrostroi.OptimisationPatch()