мое желание найти истину в том, как всё это работает
В общих чертах смысл такой. Когда игрок нажимает ТАВ, движок напрямую вызывает функцию скрипта светофора, а код сообщения указывает светофору, что он должен сделать, то есть, в данном случае - прореагировать на этот запрос.
Когда же запрос отсылает маркер, технически в скрипте светофора происходит все то же самое. Но есть одно, вроде как незначительное, отличие.
Я для своих рассуждений воспользуюсь фрагментом скрипта светофора, любезно опубликованным Игорем. Приводить его здесь не буду, кто разбирается в скриптах, сам запросто это найдет. Это скрипт выходного светофора А3 - "...\Exit.lua".
(
Сразу честно оговорюсь, я пишу после очень поверхностного просмотра скрипта, так как сейчас у меня голова забита другими проектами и мне просто не до того, чтобы проводить глубокий анализ. Если моё понимание неверно, то и выводы будут ошибочны, так что я пишу всего лишь предположения, надеюсь, Игорь меня поправит, если я не туда заверну ).
Логика работы такая. Когда светофор получил запрос, он проверяет, насколько давно был принят аналогичный запрос. Если это время меньше 0.5 сек (то есть, 2 ТАВ-а подряд), то светофор работает по сценарию открывания в поездном режиме. А если больше - светофор делает вывод, что это одиночный ТАВ и работает по сценарию маневрового режима. Я считаю, что эта схема неплохо придумана, но у неё есть изъян. Какой?
Дело в том, что первый запрос (неважно, от маркера или от игрока) по-любому вызовет блок запуска светофора в маневровый режим. И только второй запрос (если это двойной ТАВ) запустит поездной режим с рассылкой сообщений и т.п.. Насколько это критично, я не могу сказать, для этого надо изучить все процессы, происходящие при отработке функции
SetIndication(). Но, в любом случае, получается, что при двойном ТАВ-е светофор начинает выполнять одну функцию и практически сразу же отменяет или прерывает её, переключившись в другой режим.
Насколько это
может быть опасно? Если в функции нет никаких временных задержек ит.п., то это не опасно, хотя и нежелательно. Но если есть какие-то тайминги, ответ очевиден - все процессы, которые будут отложены по времени, так и не завершатся. Это уже первый шаг к крашу.
Теперь я расскажу, в чем отличие между запросом от игрока и маркера. Если мои предположения выше верны, и у функции
SetIndication() есть блоки с задержками, то запросы от игрока и от маркера прервут её работу на разных этапах. Игрок, как бы ни старался, сделает колоссальную (по меркам программы, разумеется) паузу между запросами, и это может позволить функции что-то успеть сделать. В этом случае конечное состояние светофора будет зависеть от всего: от скорости кликов игрока, от частоты кадров, от архитектуры путей... Маркер же отсылает 2 запроса в течении 1 кадра. То есть, эта функция однозначно запустится, что-то сделает, но ни один тайминг никогда, ни при каких обстоятельствах, не сработает.
Я думаю, что частые случаи зажигания белого огня на двойной ТАВ (и разное поведение при разных источниках запросов) - следствие именно этого явления. Могу только предложить переписать этот блок скрипта так, чтобы получив запрос, светофор ждал с секунду, и, если будет второй запрос, работал в поездном режиме, если не будет - в маневровом. Так удастся сделать активацию только одного режима. Если мои заключения верны, то это может вылечить проблему открывания.
Ещё раз повторюсь, это всего лишь предположения.
Почему один маркер открывает выходной бело-лунным, а два маркера подряд зелёным? Ведь получается 4 раза tab нажали в кодах маркеров?
Нет, это не 4 раза ТАВ нажали, а 2х2 с интервалом в 2 секунды, то есть, фактически, светофор должен был за это время закончить все процессы, вызванные первым двойным ТАВ-ом и получить второй запрос в "режиме ожидания". Меня больше удивляет, почему он не погас при этом полностью, повторный запрос у меня обычно приводит именно к этому.