Donate with PayPal button New New

+ Ответить в теме
Страница 1 из 3 1 2 3 ПоследняяПоследняя
Показано с 1 по 10 из 21

Тема: Скрипт вагона

  1. #1
    Пользователь Аватар для TRam_
    Регистрация
    22.09.2009
    Возраст
    33
    Сообщений
    16,432

    Script Скрипт вагона

    в формате 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)

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

  2. Сказали спасибо: (5)


  3. #Trainz
    Реклама
    Регистрация
    Постоянная
    Возраст
    2010
    Сообщений
    Много

    Donate with PayPal button N3v New New

     

  4. #2
    Пользователь Аватар для TRam_
    Регистрация
    22.09.2009
    Возраст
    33
    Сообщений
    16,432
    Автор

    По умолчанию

    Для этого в трс есть специальный класс - 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","TPhandl er");
    //что-то нужное
    }
    Есть ещё одна функция, 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 в 02:15.

  5. #3
    Пользователь Аватар для TRam_
    Регистрация
    22.09.2009
    Возраст
    33
    Сообщений
    16,432
    Автор

    Script

    Код:
    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();
    
        		} 
    };

  6. Сказал спасибо:


  7. #4
    Пользователь Аватар для TRam_
    Регистрация
    22.09.2009
    Возраст
    33
    Сообщений
    16,432
    Автор

    По умолчанию

    надеюсь, кому-то это поможет

  8. #5
    Пользователь Аватар для Forum_del
    Регистрация
    19.03.2012
    Сообщений
    38

    По умолчанию

    Цитата Сообщение от TRam_ Посмотреть сообщение
    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;
    }}

  9. #6
    Пользователь Аватар для Dandi
    Регистрация
    12.10.2009
    Страна
    Адрес
    Волгоград
    Возраст
    32
    Сообщений
    19

    По умолчанию

    TRam_, вопрос один закрался. Использование в SetCoupler else if'ов вместо switch case'ов как-нибудь аргументированно? (исключая аргумент "мне так захотелось")

  10. #7
    Пользователь Аватар для TRam_
    Регистрация
    22.09.2009
    Возраст
    33
    Сообщений
    16,432
    Автор

    По умолчанию

    не аргументировано- это копипаста со скрипта 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');
    }
    }
    Последний раз редактировалось TRam_; 21.10.2009 в 14:29.

  11. #8
    Пользователь Аватар для Почтовик
    Регистрация
    19.09.2009
    Сообщений
    179

    По умолчанию

    Володь, спасибо за урок

  12. #9
    Пользователь Аватар для Чингиз-хан
    Регистрация
    20.09.2009
    Страна
    Адрес
    Москва
    Возраст
    43
    Сообщений
    294

    По умолчанию

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

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

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

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

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

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

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

  13. #10
    Пользователь Аватар для TRam_
    Регистрация
    22.09.2009
    Возраст
    33
    Сообщений
    16,432
    Автор

    По умолчанию

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

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

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

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


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

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

    "a.

    пробежав поиском по скрипту получаем все точки, которые там требуются, тем более что их название является либо транслитным, либо английским названием звука...
    Последний раз редактировалось TRam_; 23.10.2009 в 15:49.

+ Ответить в теме

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения