PDA

Просмотр полной версии : Скрипт вагона



TRam_
21.10.2009, 00:47
в формате doc
http://dump.ru/file/3619559


Простейшие скрипты

Что такое скрипты? Это маленькие подпрограммы, на которых можно создавать различные явления игровового мира, в народе называемые "фитчами"(feature - свойство). В данном уроке постараюсь объяснить, как написать простой (и не очень глючный) скрипт для какого-нибудь вагона. Сразу скажу, что я смог его только откомпилировать, но в самой игре не смотрел (видюха не поддерживает openGL). Кое-что из объектно-ореентированного программирования я уже писал на railunion'e, остальное лучше почитать в любой книге по объектно-ориентированному языку программирования (лучше семейства Си - C++, C#, Java). Будем считать, что кое-что вы из этого знаете. Итак, допустим, нам требуется сделать вагон, который будет менять разъединённые шланги тормозной магистрали на соединённые, если он хвостовой - дополнительно устанавливать диск хвоста поезда, и при проследовании моста будет издавать дополнительный звук, в снежный день будет пылить снегом.
Начнём с того, что внимательно поищем зацепки, с помощью которых мы сможем ухватиться для обнаружения и обработки того или иного события. Пока предположу, что у вас trainz не ниже Классика (в 2006 одной из вещей нет).
Мы скачали с files.auran.com архив TRS2006-API.zip , и распаковали содержащийся в нём index.chm . Хотя по применимости к 2009 он несколько устарел, всё новое можете посмотреть на сайте trainzdev.com либо почитав базовые скрипты в вашей директории trainz (папка scripts).
Открываем в index.chm раздел Class API Reference, в нём подраздел с таким же названием. Видим длинный список всех базовых классов, которые описаны в скриптах любой trainz 2006 . Нам потребуется класс Vehicle (Вагон), все его родительские классы, а также некоторы другие, которые я укажу позже. Советую перед этим поставить любой электронный cловарь (либо переводчик), так как описание на английском.
Начнём с самой первой функции, которая стоит в оглавлении. В данном случае её можно назвать самой главной. Это

public void Init (void)

(расшифрую - публичная(её может вызвать кто-угодно), не возвращающая ничего, и не нимеющая аргументов функция "иницализация" )
по ссылке находим её описание - Called by Trainz to initialize this Vehicle. (вызывается движком трейнз для инициализации объекта Вагон).
Т.Е. если в эту функцию чего-нибудь добавить, то при инициализации вагона она будет вызвана, а наше добавление выполнится. Инициализация вагона (да и вообще почти всех объектов класса MeshObject и его подклассов, в т.ч. Vehicle) происходит всего 1 раз - при постановке их на карту либо при открытии карты(за исключением кабины). При входе в быстрый машинист переинициализации НЕ ПРОИСХОДИТ, поэтому этот переход надо писать отдельно.
Но там написано замечание - If overriding this method to perform your own custom vehicle initialization, always call back to this parent method via the inherited keyword.
Перевожу - "если вы делаете свой собственный скрипт, вы обязаны вызвать родительский метод с помощью тега inherited". Это значит, что лучше написать своё описание в своём собственном скрипте так
public void Init (void)
{
inherited(void);
//наши добавления
}


Значит это следующее - когда движок вызовет Init вагона с нашим собственным классом, то он в начале выполнит все инструкции класса-родителя (в данном случае vehicle), а затем выполнит все наши инструкции.
С тем, кто будет наш скрипт "запускать", разобрались. Смотрим дальше.

следующая функция public native Train GetMyTrain (void) .

Но в описании её написали как public native Train Vehicle.GetMyTrain(void) . Зачем же нужна эта часть "Vehicle." ?
А вот зачем. Мы вызываем функцию некого объекта. А объект, чья функкция вызывается, тоже надо указать, и это указание позволяет нам управлять как функциями нашего объекта, так и функциями других объектов(если они публичные). Вызов функции нашего объекта вообще-то записывается me.GetMyTrain(void); , но для простоты это же можно записать как GetMyTrain(void); Различия между этими 2 записями никакой нет, но лично я предпочитаю 1 - сразу понятно, над каким объектом проводится функция (т.е. над нами же)
Она нам тоже понадобится. Как мы видим, она возвращает объект класса Поезд, которому принадлежит этот вагон ( Gets the Train this vehicle belongs to.). Но о этом попозже.
Далее идёт public native bool GetDirectionRelativeToTrain (void) . Очнь полезная функция. Определяет, где перед вагона и где его зад относительно поезда. Понадобится нам, когда будем определять, какая шланга у нас соединена, а какая - нет.
(заодно и поставим диск конца поезда)

Полезна и public native bool IsOnBridge (void) - определяет, находится ли наш вагон на мосту.
Прокручиваем АПИ далее, и видим табличку с заголовом Vehicle object messages . Перевод описания системы сообщений есть на трейнсиме (ссылку можете найти на railunion'e), и в данном случае нам понадобится 2 и 3
"Vehicle","Coupled" посылаемое от сцепляемого вагона всем остальным объектам.
"Vehicle" "Decoupled" посылаемое от одного из 2 расцепляемых вагонов всем остальным объектам. В 2006 она плохо работала, в последующих её исправили (об этом я и сказал в самом начале), но я сделаю "заплатку" для работы в 2006.

А теперь смотрим родительские классы. Из класса Trackside нам пока ничего не понадобится, из MapObject - тоже.

А вот из MeshObject кое-что нам понадобится. А именно
public native MeshObject MeshObject.SetFXAttachment(string effectName, Asset asset)

Как вы поняли, именно этой функцией мы будем цеплять мешь. А так как объект меши нам не нужен(честно, об этом объекте я узнал когда писал эту статью :) ), то можем его никому не возвращать. То есть записи
MeshObject MO= (cast<MeshObject>me).SetFXAttachment("front_couple",myScepkaAsset); //так тут мы явно преобразовали наш объект из нашего класса в класс MeshObject
MeshObject MO= me.SetFXAttachment("front_couple",myScepkaAsset);
MeshObject MO= SetFXAttachment("front_couple",myScepkaAsset);
me.SetFXAttachment("front_couple",myScepkaAsset);
SetFXAttachment("front_couple",myScepkaAsset);
(cast<MeshObject>me).SetFXAttachment("front_couple",myScepkaAsset);


для данного случая абсолютно идентичны.
Ну а чтобы отцепить мешь, можно провести

SetFXAttachment("front_couple",null);

где под null понимается указатель на несуществующий объект (тоесть мы именно такой несуществующий объект цепляем вместо старого, в результате на месте сцепки у нас ничего нет). Кстати, 2004 не умела такое делать - там надо было цеплять только существующую мешь (там для имитации полной отцепки новая мешь должна была быть невидимой)

Как вы догадались, string effectName - это имя эффекта, прописанное в конфиге (в примере - довольно распространённое имя "front_couple", используемое в оснащённых скриптами AlexEF'a локах).

Далее нам потребуется класс Asset, который представляет ссылку на "дополнение"(мы его называем допом, куидом(что кстати неверно)), которое установлено в CMP (а не объект, стоящий на карте).

Но в начале мы хотя бы должны знать, какие именно "дополнения" нам потребуются. Для этого лучше всего использовать kuid-table нашего же вагона. Так как эта table ("таблица") находится вне скрипта, то её содержимое можно менять, а значит скрипт можно будет ставить вагонам с разными сцепками.

Чтобы её получить, нам надо посмотреть ещё более общий родитель класса Vehicle - класс TrainzGameObject .

В нём всего 2 функции, одна из которых нам нужна - это public Asset TrainzGameObject.GetAsset(void) С помощью этой функции мы получим "дополнение" нашего же вагона. Например так

Asset MyAsset = (cast<TrainzGameObject>me).GetAsset(void);

а можно намного короче

Asset MyAsset = GetAsset();

значат эти 2 строки одно и то же, но, думаю, начинающим 1 вариант более понятен.

А как же получать это самое kuid-table получить-то из "дополнения" нашего вагона?

А функцией public native Asset Asset.FindAsset(string kuidTableAssetName) .

А string kuidTableAssetName - строка с именем из kuid-table . Пуолучение ассета, написанного в куид-тейбле как

SA3-uncoupled <kuid:19878:142>

можно сделать так

Asset MyAsset = (cast<TrainzGameObject>me).GetAsset(void);
Asset SA3_coupled = MyAsset.FindAsset("SA3-uncoupled");

или

Asset SA3_uncouped = GetAsset().FindAsset("SA3-uncoupled");

Только учитываем, что все пересенные и ссылки, которыми могут пользоваться другие функции нашего скрипта, должны быть написаны вне функций (глобальные переменные).

Осталось посмотреть ещё 4 класса. Первым будет класс Train , из которого нам понадобится 2 функции -

public native Vehicle[] Train.GetVehicles (void) - получаем массив ссылок на все вагоны нашего поезда в порядке следования от головы, и с нумерацией, начинающейся с 0.

Чтобы наш вагон нашёл этот массив вагонов нужно сделать

Train MyTrain= (cast<Vehicle>me).GetMyTrain(void);
Vehicle[] VehicleArray= MyTrain.GetVehicles (void);

а можно кратко

Vehicle[] VehicleArray= GetMyTrain().GetVehicles();

Из этого класса нам потребуется также функция определения скорости (чтоб поезд не снежил во время стоянки) -

public native float Train.GetVelocity (void)

но проблема в том, что получаемая скорость имеет знак, а нам надо получать её абсолютную величину (модуль).

TRam_
21.10.2009, 00:47
Для этого в трс есть специальный класс - Math . А в нём - функция public float Math.Fabs ( float p_v )

(думаю abs() известна всем прогерам, а Fabs() - abs() для дробных с плавающей запятой :) )

И вот интересная деталь - мы не можем получить ссылки ни на один объект класса Math .

Для этого случая ауран придумал, что ссылка на объект Math имеется в ЛЮБОМ инициализированном объекте (к которому этот класс подключили)

Значит в скрипте будем писать

Train MyTrain= (cast<Vehicle>me).GetMyTrain(void);

float a = MyTrain.GetVelocity(void);

a=Math.Fabs(a);

или кратко

float a=Math.Fabs( GetMyTrain().GetVelocity() );

Предпоследний класс - World . Самый всезнающий класс. Знает все стрелки, триггеры, вагоны, поезда, погоду, куиды и прочее :)

но пока нам нужна погода...

определение погоды идёт public native int World.GetWeatherType(void)

снежная соотвествует значениям этой функции, больше 4 (0 и 1 - ясно, 2, 3 и 4 - дождь)

ссылок на World , как и Math, мы не можем получить, поэтому движок их нам сам даёт.

.... и звуки

public native float World.PlaySound(Asset asset, string filename, float volume, float minDistance, float maxDistance, GameObject target, string attachmentPoint)

основная скриптовая воспроизводилка звука.

замечу, что работает криво, звуки красивыми и безглючными получаются не всегда, ну и ладно.


Зато можно воспроизвести звук с увеличенной в volume раз громкостью, которая будет постоянна на расстоянии до minDistance метров от точки привязки attachmentPoint, а затем линейно затухнет до расстояния maxDistance метров. Воспроизводиться она GameObject'е (GameObject - класс-отец TrainzGameObject , и, получается, прадед Vehicle :) ), а звуки будут браться из asset , причём путь к ним из папки допа будет указан в строке filename .

Ну и дошли мы наконец до GameObject'а, который позволяет работать с системой сообщений. Нам потребуются 3 функции

public native void GameObject.PostMessage(GameObject dst, string major, string minor, float seconds )

функция, пересылающая сообщение объекту dst, с соотвествующими полями строка major и строка minor

(у сообщения есть ещё 2 поля - объект-источник и объект-приёмник)

Главный приёмник сообщений

public native void GameObject.AddHandler( GameObject target, string major, string minor, string handler)


работает очень хитро. Когда его применяют к объекту, он, если посылается сообщение к объекту target с полями string major, string minor то он ищет в коде функцию со аргументом Message, имя которой написано в строке handler, и вызывает её. (аргументом становится то самое посланное сообщение)

например, ловля сообщения "Train","NotifyPantographs" от поезда всем объектам (в том числе и нашему вагону) делается так

void TPhandler(Message Msg)
{
if(Msg.src==/*кто же это нам сообщение послал о токоприёмниках? */)
{
//делаем то-то
}
//другая обработка
}


public void Init(void)
{
inherited();
//что-то нужное
AddHandler(me,"Train","NotifyPantographs","TPhandler");
//что-то нужное
}
Есть ещё одна функция, public native void GameObject.Sniff(GameObject target, string major, string minor, bool state)

которая может заставлять объект пересылать нам сообщение предназначенное ему (причём в сообщениии будет указан не он а первоисточник)


ну и было бы не честно не рассказать о системе потоков, которая, на мой взгляд, являестся главным преимуществом Trainz Game Script .

Мы можем объявить функцию потоком. Поток - это отдельный код, который может выполняться одновременно с другими процессами, текущими в игре. Правда, для этого его надо усыпить. Для этого придумана функция public native void GameObject.Sleep ( float seconds ) которая заставляет поток засыпать на seconds секунд.

описание такое

thread void MyPotok()

{ //что-то делается

(cast<GameObject>me).Sleep(10); //полная запись сна на 10 сек

//ещё что-то делается

Sleep(1.1); //спим 1.1 секунду краткая запись

//ещё что-то делается

}

Только теперь мы можем приступить к написанию скрипта. Кое-что скопирую из AlexEf овского

Идея по такая - устанавливаем на наш вагон хендлер, который будет обрабатывать сцепку нашего вагона

и ещё один хендлер обрабатывающий расцепку вагона. Так как о расцепке вообще сообщает только

один из расцепляемых вагонов, будем проверять и их сообщения о расцепке.

Для снежной пыли сделаем отдельный поток, а для звука моста - специальный поток с проверкой "запуск не более одного"

TRam_
21.10.2009, 00:48
include "Vehicle.gs"


class NewRussianVehicle isclass Vehicle
{

Vehicle inFront;
Vehicle inBack;

Asset SA3_coupled, SA3_uncouped, Disk,MyAsset1;

float currentVelocity=0;

bool we_are_on_brige=false;


void SetCoupler(int pos, bool direction)
{
//// устонавливает соотвецтвующий тип сцепки для переда и зада вагона
//// в зависимости от положения и направления вагона в составе
//// public void SetCouplerType(int pos, bool direction);
//// pos :
//// 0 - одиночный
//// 1 - Первый
//// 2 - В центре
//// 3 - Последний
////
//// durection :
//// true - направление вагона соотвецтвует направлению состава
//// false - направление вагона не соотвецтвует направлению состава

if (pos == 0) //// вагон одиночный
{
SetFXAttachment ("front_couple", SA3_uncouped);
SetFXAttachment ("back_couple", SA3_uncouped);
SetFXAttachment ("front_disk", null);
SetFXAttachment ("back_disk", null);
}
else if (pos == 1) //// вагон в начале состава
{
if (direction)
{
SetFXAttachment ("front_couple", SA3_uncouped);
SetFXAttachment ("back_couple", SA3_coupled);
SetFXAttachment ("front_disk", null);
SetFXAttachment ("back_disk", null);
}
else
{
SetFXAttachment ("front_couple", SA3_coupled);
SetFXAttachment ("back_couple", SA3_uncouped);
SetFXAttachment ("front_disk", null);
SetFXAttachment ("back_disk", null);
}
}
else if (pos == 2) //// вагон в центре состава
{
SetFXAttachment ("front_couple", SA3_coupled);
SetFXAttachment ("back_couple", SA3_coupled);
SetFXAttachment ("front_disk", null);
SetFXAttachment ("back_disk", null);
}
else if (pos == 3) //// вагон в конце состава
{
if (direction)
{
SetFXAttachment ("front_couple", SA3_coupled);
SetFXAttachment ("back_couple", SA3_uncouped);
SetFXAttachment ("front_disk", null);
SetFXAttachment ("back_disk", Disk);
}
else
{
SetFXAttachment ("front_couple", SA3_uncouped);
SetFXAttachment ("back_couple", SA3_coupled);
SetFXAttachment ("front_disk", Disk);
SetFXAttachment ("back_disk", null);
}
}
}







int GetMyNumber(Vehicle[] TrainVehiclesArray)
{
int i=0,ArraySize = TrainVehiclesArray.size();

Vehicle MyVeh=(cast<Vehicle>me);

while(i<ArraySize)
{
if(TrainVehiclesArray[i]==MyVeh)
return i;
i++;
}

return 0;
}


void MyPosition(void)
{

Train MyTrain=me.GetMyTrain();
if(MyTrain!=null)
{
Vehicle[] TrainVehiclesArray = MyTrain.GetVehicles();




int a=me.GetMyNumber(TrainVehiclesArray);
int size_of_train=TrainVehiclesArray.size();

bool direction = (cast<Vehicle>me).GetDirectionRelativeToTrain();


if(size_of_train==1) //вагон одиночный
{
inFront=null;
inBack=null;
SetCoupler(0,direction);
}

else if(a==0) //// вагонов больше одного, этот вагон находиться первым в составе
{
inFront=null;
inBack=TrainVehiclesArray[1];
SetCoupler(1,direction);
}
else if(a<(size_of_train-1)) //// вагонов больше одного, этот вагон находиться в центре состава
{
inFront=TrainVehiclesArray[a-1];
inBack=TrainVehiclesArray[a+1];
SetCoupler(2,direction);
}
else //// вагонов больше одного, этот вагон находиться в конце состава
{
inFront=TrainVehiclesArray[size_of_train-2];
inBack=null;
SetCoupler(3,direction);
}



}



}






void CoupleHandler(Message msg)
{
if(msg.src==me) //мы сцепились
{
me.MyPosition();
}
}


void DecoupleHandler(Message msg)
{

if(msg.src==me or msg.src==inFront or msg.src==inBack) //мы, либо соседний вагон, расцепилсись
{
me.MyPosition();
}
}




thread void SoundLooper()
{
// звук должен быть всего 1, значит, если во время работы одного этого потока вдруг был запущен другой
// то этот другой работать не должен.

if(!we_are_on_brige)
{
we_are_on_brige=true;

while(currentVelocity>20 and me.IsOnBridge()==true)
{
me.Sleep(World.PlaySound(MyAsset1,"brigesound.wav",1.0,14.0,1000.0,me,"a.bog0"));
}
we_are_on_brige=false;
}



}



thread void VehicleLooper()
{

me.Sleep(0.6); //ждём инициализации

Train train1=me.GetMyTrain();

while(train1!=null) //бесконечный цикл
{
train1=me.GetMyTrain();
if(train1!=null)
{
currentVelocity=Math.Fabs(train1.GetVelocity())*3. 6; //переводим из м/с в км/ч
if(me.IsOnBridge()==true)
{
SoundLooper();
}

if(currentVelocity>15 and World.GetWeatherType()>4)
PostMessage(me,"pfx","+0+1",0);
else
PostMessage(me,"pfx","-0-1",0);


if(World.GetTrainzVersion()<=2.6) //заплатка на 2006 версию трейнз
{
me.PostMessage(me,"Vehicle","Decoupled",0);//заставляем наш вагон проверить, не отцепили ли от него другие вагоны
}



}
else
currentVelocity=0;

me.Sleep(10);
}

}






public void Init(void)
{
inherited();

//Ищем в Kuid-Table сцепки
//SA3_coupled - сомкнутоя сцепка
//SA3_uncouped - разомкнутоя сцепка
//Disk - диск хвоста поезда


MyAsset1=me.GetAsset();

Disk = MyAsset1.FindAsset("Disk");
SA3_coupled = MyAsset1.FindAsset("SA3-coupled");
SA3_uncouped = MyAsset1.FindAsset("SA3-uncoupled");





PostMessage(me,"pfx","-0-1",0.9); //с некоторой задержкой отключаем снежную пыль

me.AddHandler(me,"Vehicle","Coupled","CoupleHandler");
me.AddHandler(me,"Vehicle","Decoupled","DecoupleHandler");

me.PostMessage(me,"Vehicle","Coupled",0.8); //изображаем, как будто вагон наш сцепился :)
//задержка нужна для того, чтобы модель успела прогрузиться

me.VehicleLooper();

}
};

TRam_
21.10.2009, 00:49
надеюсь, кому-то это поможет :connie_es:

Forum_del
21.10.2009, 12:03
thread void MyPotok()

{ //что-то делается

(cast<GameObject>me).Sleep(10); //полная запись сна на 10 сек

//ещё что-то делается

Sleep(1.1); //спим 1.1 секунду краткая запись

//ещё что-то делается

}
void SprositiPolzovatela()
{
for(int i=1;i<5;i++)
{
cout << "OK? (y/n) ";
cin >> c;
// bolshie i malenkie bukvi
if(c!='y' && c!='Y' && c!='n' && c!='N') i--;
else i=10;
}}

Dandi
21.10.2009, 12:15
TRam_ (https://forum.trainzup.net/member.php?u=67), вопрос один закрался. Использование в SetCoupler else if'ов вместо switch case'ов как-нибудь аргументированно? (исключая аргумент "мне так захотелось")

TRam_
21.10.2009, 12:58
не аргументировано- это копипаста со скрипта AlexEF'а. Так что можно заменить эту функцию на




void SetCoupler(int pos, bool direction)
{
switch(pos)
{
case 0 : //// вагон одиночный
{
SetFXAttachment ("front_couple", SA3_uncouped);
SetFXAttachment ("back_couple", SA3_uncouped);
SetFXAttachment ("front_disk", null);
SetFXAttachment ("back_disk", null);
break;
}

case 1 : //// вагон в начале состава
{
if (direction)
{
SetFXAttachment ("front_couple", SA3_uncouped);
SetFXAttachment ("back_couple", SA3_coupled);
SetFXAttachment ("front_disk", null);
SetFXAttachment ("back_disk", null);
}
else
{
SetFXAttachment ("front_couple", SA3_coupled);
SetFXAttachment ("back_couple", SA3_uncouped);
SetFXAttachment ("front_disk", null);
SetFXAttachment ("back_disk", null);
}
break;
}
case 2 : //// вагон в центре состава
{
SetFXAttachment ("front_couple", SA3_coupled);
SetFXAttachment ("back_couple", SA3_coupled);
SetFXAttachment ("front_disk", null);
SetFXAttachment ("back_disk", null);
break;
}
default : //// вагон в конце состава
{
if (direction)
{
SetFXAttachment ("front_couple", SA3_coupled);
SetFXAttachment ("back_couple", SA3_uncouped);
SetFXAttachment ("front_disk", null);
SetFXAttachment ("back_disk", Disk);
}
else
{
SetFXAttachment ("front_couple", SA3_uncouped);
SetFXAttachment ("back_couple", SA3_coupled);
SetFXAttachment ("front_disk", Disk);
SetFXAttachment ("back_disk", null);
}
}
}
}



void SprositiPolzovatela()
{
for(int i=1;i<5;i++)
{
cout << "OK? (y/n) ";
cin >> c;
// bolshie i malenkie bukvi
if(c!='y' && c!='Y' && c!='n' && c!='N') i--;
else i=10;
}}

void Oshibka_Polzovatela()
{
c='0';
while(c!='y' && c!='n')
{
cout << "OK? (y/n) ";
cin >> c;
if(c<'a')
c=c+('a'-'A');
}
}

Почтовик
21.10.2009, 21:45
Володь, спасибо за урок

Чингиз-хан
23.10.2009, 13:51
Это все прекрасно, но можно сделать скрипт вагона универсальный для всех новых создаваемых вагонов.

Скажем так:
1. Свет включался и выключался по разному и с помощью кнопки.
2. Сцепка.
3. Аним двери.
4. Пассажиры.
5. Ну и так далее.
И указать где и какие точки привязки разместить.
Чтобы разработчикам вагонов просто прописать данный скрипт и все.

Этого так не хватает. Вон Женя делает Шексну, вместо того чтоб отвлекать одного из скриптеров, взял бы и скачал такой универсальный скрипт и вставил его в вагон и все будут довольны.

Я прекрасно понимаю, что щас скажите а сделай сам, ну зачем так грубо, яже предлогаю дело.

Уважаемый Владимир Tram_ не рассмотрите мое предложение сделать данный скрипт в виде урока, не описывать скрипт, а просто дать такой и показать где что надо для него расставить.

С глубоким уважением Владислав.

Простите меня за данный пост "КРИКА"

TRam_
23.10.2009, 14:25
наверно создаваемых пассажирских вагонов (тот что описан выше - для грузовых)

со светом один вопрос. Движок трейнз не умеет делать тени в кабине, но зато скрипт умеет изменять ячркость освещения полигон в ней. Поэтому мне сейчас не хватает ни информации по зависимости освещённости от времени суток и погоды. (а так как трейнз не запускается, на "ощупь" сделать эту зависимость физически не смогу. Может кто-нибудь с фотометром 2 графика освещённости от времени сделает?(пасмурная/ясно) ). Ещё хуже со звуками - это единственная вещь в трс, которая требует очень продолжительных плясок с бубнами, а плясать с бубнами без информации о результате - верх безумия.

Для шексаны я уже делаю то, что в состоянии проверить только по коду, да и то очень медленно. Кстати, у этого вагона есть несколько индивидуальных особенностей, так что везде его поставить нельзя будет...


2. Сцепка.всм в режима свободной камеры дёргать ручку расцепки? можно... (если о обычной сцепке, то можно и сейчас скрипт AlexEF'а прикрутить, если на старой модели сделать точки привязки)


а по поводу подключения скрипта самый надёжный способ - внимательно посмотреть конфиг, и поставраться делать все меши и дымы такими же, как и там.

А для поиска точек привязки звука открываем скрипт в блокноте, затем правка - найти

"a.

пробежав поиском по скрипту получаем все точки, которые там требуются, тем более что их название является либо транслитным, либо английским названием звука...

kemal
25.10.2009, 11:31
всм в режима свободной камеры дёргать ручку расцепки? можно...
Как???
Я думал, дергать рычаги можно только в кабине..

Snark
25.10.2009, 12:32
kemal, рычаги можно дергать только в салоне, ты прав. Наверное под "свободной камерой" имеется ввиду freeintcam. Кстати, было бы интересно реализовать стоп-краны в пассажирских вагонах.

Чингиз-хан
25.10.2009, 12:39
kemal, интересно реализовать стоп-краны в пассажирских вагонах.

Зачем? Да и корее всего это просто нельзя, у локомотива свой движок.

Forum_del
25.10.2009, 12:58
Кстати, было бы интересно реализовать стоп-краны в пассажирских вагонах.
Провокационный вопрос: зачем?

kemal
25.10.2009, 16:12
TRam_, а можно ли отследить изменение направления поезда? Чтобы переменные inFront и inBack местами менялись.

TRam_
25.10.2009, 18:39
TRam_, а можно ли отследить изменение направления поезда? Чтобы переменные inFront и inBack местами менялись. честно, когда писал тот скрипт, забыл об этом событии (Скорее всего нет), хотя оно там и не важно - каждый вагон следит только за собой, а знать, передний или задний вагон ему сообщили о расцепе не надо так как перепроверяться при расцепе будут оба. При сцепе вагон сам себе это сообщает


под "свободной камерой" имеется ввиду freeintcamименно её и имел в виду , при виде снаружи есть сообщение только о наведении мыши на вагон (кроме "свойств")


Кстати, было бы интересно реализовать стоп-краны в пассажирских вагонах.эти как раз нужны. Чтобы потом забыть, что где-то сорвали стоп-кран, и на тормозах трогаться :)

реализация - SetBrakePipeEfficiency(0.0);

Олег Шмигельский
01.11.2011, 18:03
файл удален на dump.ru перевыложи плиз!

Skif
01.11.2011, 19:10
Класс! Давно пора, только формат форума не очень удобен для такого :(( . Может, что то вроде блога или вики замутим?


Поддержу про стоп-кран. Мелочь, а приятно для салона!

TRam_
01.11.2011, 19:42
Со временем оказалось, что эта функция всё таки не вызывает разрядки ТМ. К сожалению.

Skif
01.11.2011, 21:00
Да поставить в салоне кран машиниста с двумя положениями - перекрыша и экстренное. И настроить как для лока. Сработает?

TRam_
01.11.2011, 21:20
Ну, в общем случае надо делать свой собственный КабинКонтрол для него (т.к. у вагонов по умолчанию никаких рукояток нет). Ну а идея верная - синхронизировать с краном машиниста.



New