Последняя промежуточная версия.
- добавлен штраф по скорости, величина от 10 до 50% задаётся в настройках, по умолчанию 15%.
В случае, если сцепляемые локомотивы не умеют работать в СМЕ, либо превышено их количество, либо неверный порядок следования, то все локомотивы получают штраф, и скорость движения состава определяется наименьшей скоростью.
Исключение составляют маневровые тепловозы и паровозы. Они сигнализируют о штрафе для др. локомотивов всегда, но сами не получают штраф. У них и так скорость снижена, см. паровоз 9П, тепловозы ТЭМ1, ТЭМ2, ТЭМ2У. Мне такой вариант показался более интересным. Если заблуждаюсь, можно мне это объяснить, и у маневровых не будет исключения.
С реализацией штрафа есть серьёзные проблемы.
Например, я пока не знаю, как сделать (и реализуемо ли это) совместное использование локомотивов разных моделей, см., например, строчку для 2ТЭ10М в xls.
Люто не хватает переменной, позволяющей опросить идентификатор соседей справа/слева. Если бы была переменная, позволяющая задать положительное или отрицательное смещение в виде параметра и возвращающая id элемента в составе, это бы очень сильно помогло.
Не хватает возможности вызывать подпрограммы, из-за этого пришлось в чёрную копипастить, потому как ограничение реализовано через 3 вызова cb.
Теперь, как это было сделано.
Для ограничения скорости использован cb speed, для задания скорости в меню покупки использован отдельный cb purchase_speed. После серии опытов на паровозах было выяснено, что мы можем опросить локомотив, используя область видимости PARENT, и текущий элемент, используя область видимости SELF. Другие элементы нам недоступны в силу ограничений, наложенных разработчиками на обращения в теле cb, меняющих свойства ПС. Величина скорости должна вернуться сразу же в конце тела cb speed. Другими словами, штраф можно наложить на текущий элемент, а для сравнения можно использовать только его позицию и данные о локомотиве. Я решил зайти с др. стороны. Для этого задействовал cb bitmask_vehicle_info, которая возвращает 8 бит пользовательских данных, и стал трактовать бит 0 как флаг, определяющий, надо ли применять штраф к составу или нет. В результате функции speed и purchase_speed упростились, там остались только величины скоростей, а логика активации режима перешла в тело bitmask_vehicle_info. Даже если один из ПС требует штрафа составу, этот штраф в силу природы переменной bitmask_consist_info будет виден и может быть применён ко всем ПС в составе. Я его применяю только для локомотивов.
Общий алгоритм таков:
1. проверяем позицию элемента, если она == 0, то считаем себя локомотивом и завершаем вызов не устанавливая признак штрафа.
2. иначе считаем себя где-то в середине состава, и опрашиваем id локомотива в области видимости PARENT и считаем кол-во элементов своего типа.
3. в обл. видимости SELF считаем кол-во элементов своего типа от текущего до конца. Разница величин, расчитанной на шаге 2 и этой, даст нам индекс локомотива нашего типа. Этой величиной мы оперируем, сравнивая её с текущей позицией в предположении, сколько элементов нашего типа уложится между локомотивом и текущим элементом. Если уложилось, сверяем СМЕ, если нет, то взводим флаг штрафа. Если текущий индекс больше положенного по СМЕ - тоже взводим, иначе возвращаем не взведённым.
Текст функций на примере 2ТЭ70, позволяющему до 4-х секций
- Код: Выделить всё
// Макс. скорость: 110 км/ч
#define MAX_SPEED 110
switch (FEAT_TRAINS, SELF, _2te70_purchase_speed,
MAX_SPEED)
{
return;
}
switch (FEAT_TRAINS, SELF, _2te70_speed,
[
STORE_TEMP(MAX_SPEED, 0),
is_penalise_speed() ? get_penalised_speed(LOAD_TEMP(0)) : LOAD_TEMP(0)
])
{
return;
}
#undef MAX_SPEED
switch (FEAT_TRAINS, SELF, _2te70_bitmask_vehicle_info3,
[
STORE_TEMP(LOAD_TEMP(0) - count_veh_id(_2te70), 0),
(last_computed_result && (position_in_consist == 2 * LOAD_TEMP(0)) &&
LOAD_TEMP(0) < 4)
])
{
1: return 0;
return FLAG_PENALISE_SPEED;
}
switch (FEAT_TRAINS, PARENT, _2te70_bitmask_vehicle_info2,
[
STORE_TEMP(count_veh_id(_2te70), 0),
vehicle_type_id == _2te70
])
{
_2te70_bitmask_vehicle_info3;
}
switch (FEAT_TRAINS, SELF, _2te70_bitmask_vehicle_info,
position_in_consist == 0)
{
1: return 0;
_2te70_bitmask_vehicle_info2;
}
Напоминаю, что в наборе все ПС длиннее 8 состоит из двух сочленённых элементов: собственно ПС и невидимого болванчика, главной задачей которого является выставления правильной величины размера (размер_ПС - 8 ). Это потому, что если для локомотивов можно применять livery_override (и задать там размер), то для вагонов это увы нельзя делать. Механизм же использовать хотелось унифицированный, а не специализированный.
Поэтому тут - "position_in_consist == 2 * LOAD_TEMP(0)" - множитель 2.
Что в итоге вышло - можете заценить.