if S.trains == nil then S.trains = {} end F.odj = {} -- F.dst - Get summer time function F.dst() if os.date().isdst then return "CEST" else return "CET" end end function F.pccheck(pos, state) if is_passive(pos) then return true end return (getstate(pos) == state) end -- F.error - Send error with error code function F.error(errorcode) error(F.errlist[errorcode]) end --[[ F.stnbasic - Basis for all station functions: (By default, nil is defined as false or "no changes") stn = Station Code side = Door opening side optime = Length of time before train departs reverse = Reverse train before departing acc = Departure Speed out = Change outside text reventry = Allow trains to pass from the reverse direction predepart = Function to execute before departure postdepart = Function to execute after departure next = Next stop ]] function F.stnbasic(stn, side, optime, reverse, acc, out, reventry, predepart, postdepart, next,track) if not event then return end if event.type == "train" then if atc_arrow then if (get_rc() or ""):match ("FREIGHT") then atc_send (reverse and "RSM" or "SM") return end local cmdstr="" local t_sched = ((optime or 15) + 1) if out then atc_set_text_outside (out) end local intext = "Unknown Station" if stn then intext = F.stnlist[stn] or stn end atc_set_text_inside (intext) cmdstr = "BBWO" .. (side or "R") if type (predepart) == "function" then predepart () end S.trains[atc_id] = { v = 1, l = (get_line() or ""), s = stn, t = (trk or "N/A"), } cmdstr = cmdstr .."D" .. math.floor((optime or 15)) .. "OCD1" if reverse then cmdstr = cmdstr .. "R" end cmdstr = cmdstr .. "S" .. (acc or "M") atc_send (cmdstr) interrupt (t_sched,"") end elseif event.type == "int" then if atc_id then local intext = "" if next then intext = "Next stop: " .. (F.stnlist[next] or next) end if type (postdepart) == "function" then postdepart () end atc_set_text_inside (intext) end end end -- F.hst - preset function for small stations (Haltestelle) function F.hst(cur, nxt, side, spd, out, trk) F.stnbasic(cur, side, 10, false, spd, out, true, nil, nil, nxt, trk) end -- F.bhf - preset function for large stations (Bahnhof) function F.bhf(cur, nxt, side, spd, out, trk) F.stnbasic(cur, side, 15, false, spd, out, true, nil, nil, nxt, trk) end -- F.kbhf - preset function for termini function F.kbhf(cur, nxt, side, spd, out, trk) F.stnbasic(cur, side, 15, true, spd, out, true, nil, nil, nxt, trk) end -- F.timing - station with timing function F.timing(d_off, d_int, cur, nxt, side, spd, out, trk, term, pre, post) local timenow = os.time() local timesincelast = (timenow+d_off) % d_int local wait = d_int - timesincelast F.stnbasic(cur, side, wait, term, spd, out, true, pre, post, nxt, trk) end -- F.brk(direction) - sends ATC B2 command function F.brk(dir) if event.type == "train" then if atc_arrow == dir then atc_send("B2S2") end end end -- Second version of the station function function F.stn2gen(stn, trk, door, ret, chout) if not stn then return end if not trk then return end if not door then return end if door~="L" and door~="R" and door~="C" then return end if not atc_arrow then return end if not F.stndet[stn] then return end if not F.stndet[stn][trk] then return end local t = F.stndet[stn][trk] local stop = false if #t==0 then return end local l = get_line() if (not l) or l==" " then return end local rc = get_rc() or "" if rc:match("FREIGHT") then atc_send (ret and "BBWRSM" or "SM") return end if event.type == "train" then for i = 1, #t, 1 do if t[i][1]==l then stop = true atc_send(string.format("BBWO%sD15OCD1%sSM", door, (ret and "R" or ""))) local intext_nxt = F.stnlist[t[i][2]] and ("Next station:\n%s\n(Track: %s)"):format(F.stnlist[t[i][2]], t[i][3] or "?") or "" local intext = ("%s\n%s"):format(F.stnlist[stn] or stn, intext_nxt) local outtext = string.format("%s (%06d)",F.lines[l].name or l, atc_id) if t[i][4] then outtext = outtext.." - "..(F.stnlist[t[i][4]] or t[i][4]) end local timenow = os.time() t[i][5] = t[i][5] or (timenow-(F.depint[l] or 300)) -- note that the "average" time is weighted t[i][6] = t[i][6] and (t[i][6]+timenow-t[i][5]+30)/2 or (timenow-t[i][5]) t[i][5] = timenow atc_set_text_inside(intext) if chout then atc_set_text_outside(outtext) end S.trains[atc_id] = { v = 2, l = (get_line() or ""), s = stn, t = (trk or "N/A"), } schedule_in(15, intext_nxt) break end end if (not stop) then atc_send(ret and "BBWRSM" or "SM") end end if event.type == "schedule" then if type(event.msg) == "string" then atc_set_text_inside(event.msg) atc_send(ret and "OCD1RSM" or "OCD1SM") end end end function F.disp2gen(stn) if not stn then return end if not F.stndet[stn] then return end local s = F.stndet[stn] local sn = F.stnlist[stn] or stn local d={{sn.."\nTrack Line\n", (string.sub(sn, 28, 54) or "").." \nDestination\n", " \nEstimated Arrival\n"}} local c=2 local t={} for i,_ in pairs(s) do t[#t+1]=i end table.sort(t) for i = 1,#t,1 do local trkname = t[i] local trk = s[trkname] for j = 1,#trk,1 do local det = trk[j] local r = (c%4==0) and (c/4+1) or ((c-c%4)/4+1) if not d[r] then d[r]={"",""} end d[r][1] = d[r][1] .. string.format("%-8s %s\n", tostring(trkname), F.lines[det[1]].name) d[r][2] = d[r][2] .. (F.lines[det[1]].ring and "Ring Line" or (F.stnlist[det[4]] or det[4] or "")).."\n" c=c+1 local earr = (det[5] or os.time())+(det[6] or F.depint[det[1]] or 600) d[r][3] = d[r][3] .. os.date("%Y-%m-%d %H:%M %Z", earr) .. "\n" end end for i = 1, #d, 1 do for j = 1, #d[1], 1 do digiline_send("d_"..tostring(i).."_"..tostring(j), d[i][j]) end end end function F.eval(expr, rettrue, retfalse) if expr then return rettrue else return retfalse end end function F.checkpoint(name,arrow,opp) if event.train then S.trains[atc_id] = "C "..name.." " if atc_arrow then S.trains[atc_id] = S.trains[atc_id]..arrow else S.trains[atc_id] = S.trains[atc_id]..opp end end end function F.atc (cmd, intext, outtext) if event.type == "train" then if atc_arrow then if cmd then atc_send (cmd) end if intext then atc_set_text_inside (intext) end if outtext then atc_set_text_outside (outtext) end end end end F.stnlist = { cg = "Colored Grasses", clockwise = "Clockwise Route", counterclockwise = "Counterclockwise Route", cras = "Crossroads ARSE7's Shop", crbfost = "Crossroads Station East", crbfsm = "Crossroads Station St. Central", crbfso = "Crossroads Station St. East", crbfsw = "Crossroads Station St. West", crch = "Crossroads City Hall", crchs = "Crossroads City Hall South", crmtrail = "Crossroads Mountain Railway Terminus", crnsw = "Crossroads North Station St. 9th Alley", crnsw2 = "Crossroads C. 2nd St./Station St. 9th Alley", crrathaus = "Crossroads City Hall", crsmacker = "Crossroads Smacker's Station", crwm = "Crossroads West Mountains", crzn = "Crossroads Central/North", elchateau = "Erstaziland-Chateau d'Erstazi", elgp = "Erstaziland-Greener Pastures", elsf = "Erstaziland-Salt Factory", evo = "EVO", grsc = "Grassy Scarp", mushroom = "Mushroom Land", neverbuild = "Neverbuild", nvbcentral = "Neverbuild Central", nvbold = "Neverbuild Old Terminus", nvboutskirts = "Neverbuild Outskirts", oc = "Ocean City", occh = "Ocean City City Hall", occrt = "Ocean City CRT Office", ocmushroom = "Ocean City Mushroom Market", ocoutskirts = "Ocean City Outskirts", phsc = "Personhood Southern Crossing", phwest = "Personhood West", scc = "Silver Coast Central", scn = "Silver Coast North", scs = "Silver Coast South", thecube = "The Cube", } F.lines = { ["AB"] = { name = "ATL Bronze Line", ring = false, [1] = { {"crch","A1"}, --[[ {"crwm","3"}, ]] {"scs","N2"}, {"scc","N2"}, {"scn","N2"}, {"cg","1"}, {"thecube","4"}, {"phsc","N"}, {"grsc", "4"}, {"phwest","1"} }, [2] = { {"phwest","1"}, {"grsc", "3"}, {"phsc","S"}, {"thecube","1"}, {"cg","2"}, {"scn","S2"}, {"scc","S2"}, {"scs","S2"}, --[[ {"crwm","4"}, ]] {"crch","A1"} }, }, ["AZ"] = { name = "ATL Zinc Line", ring = false, [1] = { {"evo","N/A"}, {"scs","N1"}, {"scc","N1"}, {"scn","N1"}, {"oc","N"}, {"elgp","N"}, {"elsf","E"}, {"elchateau","S"} }, [2] = { {"elchateau","S"}, {"elsf","W"}, {"elgp","S"}, {"oc","S"}, {"scn","S1"}, {"scc", "S1"}, {"scs","S1"}, {"evo","N/A"} }, }, ["CRT1"] = { name = "CRT 1", ring = false, [1] = { {"crsmacker", "R3"}, {"crch", "U1"}, {"crchs", "W"}, {"cras", "N"} }, [2] = { {"cras", "N"}, {"crchs", "E"}, {"crch", "U2"}, {"crsmacker", "R3"} }, }, ['CRT2'] = { name = 'CRT 2', ring = false, [1] = { {'crch', 'U6'}, {'crbfsw', 'E'}, {'crnsw', 'R1'} }, [2] = { {'crnsw', 'R1'}, {'crbfsw', 'W'}, {'crch', 'U6'} }, }, } F.stndet = {} for i, l in pairs(F.lines) do for j = 1, #l, 1 do local dir = l[j] for k = 1, #dir, 1 do local s = dir[k][1] local t = dir[k][2] if not F.stndet[s] then F.stndet[s] = {} end if not F.stndet[s][t] then F.stndet[s][t] = {} end if k~=#dir or l.ring then local nxt = dir[k==#dir and 1 or k+1] F.stndet[s][t][#F.stndet[s][t]+1] = {i, nxt[1], nxt[2], dir[#dir][1]} else local addent = true for m = 1, #l, 1 do addent = addent and (l[m][1]==dir[k]) end if addent then F.stndet[s][t][#F.stndet[s][t]+1] = {i, nil, nil, s} end end end end end F.errlist = { ["incorrect_setup"] = "Incorrect LuaATC track setup!", ["runaway_train"] = "Runaway train found!", ["train_disappeared"] = "Train has disappeared!", ["unexpected_train"] = "Train is not expected to pass!", ["wrong_direction"] = "Train passed in wrong direction!", } F.depint = { ["AB"] = 90, ["AG"] = 120, ["CRT1"] = 30, } F.dpts = { ['CRT1'] = POS(1835,5,1000), ['AG'] = POS(1399,4,2020), } function F.odd(ln) if event.type=='ext_int' then if atc_id then set_rc(event.message.rc) atc_send('SM') else if type(F.odj[ln])~='table' then F.odj[ln] = {} end for i = 1,(#F.odj[ln]) do if F.odj[ln][i]==event then return end end table.insert(F.odj[ln],1,event) end end if event.type=='train' then if F.odj[ln] and #F.odj[ln]~=0 then ev = table.remove(F.odj[ln]) if ev then set_rc(ev.message.rc) atc_send('BBWRSM') return else F.odj[ln] = {} end end atc_send('BBWR') end end function F.ods(rc, side, rev) if event.type=='train' then if atc_arrow then if string.find((get_rc() or ''),(rc or '')) then atc_send('BBWO' .. (side or 'R') .. 'D10OCD1' .. ((rev or string.find((get_rc() or ''), 'R' .. rc)) and 'R' or '')..'SM') elseif rev then atc_send('BBWRSM') end end end end function F.odc(ln, rc) interrupt_pos(F.dpts[ln],{['rc']=rc}) end