|
Raven
Пользователь
Откуда: Владик Регистрация: Февр. 2004
Всего: 408 сообщений
|
>>мне вдруг тоже чертовски интересны стали последние разработки в области диалогов. Ну, в диалогах, не в диалогах. Но наработки есть. Сегодня расскажу про одну (и постараюсь делать это более-менее регулярно). Начнём с мелочей. ВНИМАНИЕ! Всё, о чём я (пока) буду говорить - это техническая сторона скриптинга. Говорить будем про msg-файлы. Что это такое? Пронумерованный (необязательно последовательно) список строк. Имя должно совпадать с одним из имён существующих скриптов. Номер совпадает с номером одноимённого скрипта. Для работы с msg-фйалом с помощью стандартных макросов необходимо определить дефайн NAME: #define NAME номер_скрипта После этого mstr(xxx) вернёт строку xxx. Задача 1. Недостаток: привязка скрипта к какому-то там номеру. Если вы поменяете положение скрипта в scripts.lst (а номер строки, где прописан скрипт и есть номер скрипта), то скрипт перестаёт работать - т.к. не находит свою msg-шку. Решение: устранить привязку. Делаем это следующим образом. В msg на фиксированной строчке заводим определённую запись. Например, у нас есть персонаж по имени Сайег (имя из прототипа): ------------------------ {1000}{}{Сайег} ------------------------ Пишем код: ------------------------ #define LIMIT 2000 //на каком номере остановиться variable msg_num; //глобальная вара, в которую пойдёт номер найденой msg-шки <...> variable i:=1300; //ищем только в своих msg-шках, игровые не трогаем while message_str(i,1000)!=obj_name(self_obj) and i<LIMIT do i+=1; if i==LIMIT then display_msg("ERROR: msg not found."); else msg_num:=i; <...> ------------------------ Всё это легко запихивается в макрос - и вуаля! Задача 2: Мы хотим сделать набор флоатеров для персонажа, так чтобы он выбирал и говорил случайную строку из некоторого диапазона номеров в msg-файле. Но! Мы хотим, чтобы диапазон изменялся динамически - т.е. если в msg-шке у нас 15 реплик, то он выбирал 1 из 15; 20 - 1 из 20. Заимствуем принцип из предыдущей задачи, но вместо поиска по содержимому и номеру строки в наборе мсг-шек будем искать строку по содержимому в конкретной мсг-шке. Решение: Заводим такой вот msg: ------------------------ <...> //номера произвольны, главное - последовательны {231}{}{BEGIN REPLICS} {232}{}{Привет} {233}{}{Хай} {234}{}{Как дела?} <...> {240}{}{END REPLICS} <...> ------------------------ Код: ------------------------ #define LIMIT 5000 //сколько строк обрабатывать //msg_num - номер нашей msg-шки, найденный заранее <...> variable i:=1; variable first; //номер строки с первой репликой variable last; //с последней while message_str(msg_num,i)!="BEGIN REPLICS" and i<LIMIT do i+=1; if i==LIMIT then display_msg("ERROR: replics list not found"); else start:=i+1; //Начинаем искать от строки first //Ищем либо закрывающий "тэг", либо первую пустую строку while message_str(msg_num,i)!="END REPLICS" or message_str(msg_num,i)!="Error" do i+=1; last:=i-1; //проверки на ошибку не делаем, т.к. список не может быть бесконечным, пустая строка всегда найдётся //Закрывающий тэг нужен "для себя", как комментарий floater(random(first,last)); <...> ------------------------ Тормозов никаких нет, всё работает довольно шустро. Но ОБЯЗАТЕЛЬНО вводите ограничители! Бесконечный цикл подвешивает игру. Ладно, на сегодня хватит. Следущий постинг будет взаимодействие объектов, наверное. Отзывы? И, да - не стесняётесь постить свои мысли/наработки.
|
Отправлено: 11:41 - 24 Ноября, 2004
|
|
Mynah
Модератор
Откуда: Пермь Регистрация: Окт. 2004
Всего: 469 сообщений
|
Цитата:
Тормозов никаких нет, всё работает довольно шустро.
А если таких скриптов 15-20? Тоже всё ок? С устранением привязки - рулез :)
----- Scio me nihil scire
|
Отправлено: 12:52 - 24 Ноября, 2004
|
|
Raven
Пользователь
Откуда: Владик Регистрация: Февр. 2004
Всего: 408 сообщений
|
На Йцукеновском Cel 1700 всё нормально (по его словам) на схожем скрипте. На моём Athlon XP 3000+ - тоже :-) На моём бывшем 166... Не должно, по идее. Это всё выполняется один раз, в map_enter. А msg-шку можно и в LVARу запомнить, если что.
|
Отправлено: 13:01 - 24 Ноября, 2004
|
|
Mynah
Модератор
Откуда: Пермь Регистрация: Окт. 2004
Всего: 469 сообщений
|
Если кому-то интересно - могу выложить свои наработки. В частности obj_hear_obj и obj_see_obj. Мои функции вроде бы работают не так глючно как бисовские :)
----- Scio me nihil scire
|
Отправлено: 4:20 - 26 Ноября, 2004
|
|
Raven
Пользователь
Откуда: Владик Регистрация: Февр. 2004
Всего: 408 сообщений
|
>>Если кому-то интересно... Для того эта тема и создана. Выкладывайте все, без всякого "если кому-то надо". Надо. P.S. Егор планирует отдельный форум для таких вещей.
|
Отправлено: 4:37 - 26 Ноября, 2004
|
|
Alan Killenger
Пользователь
Откуда: Россия, Ижевск Регистрация: Июль 2004
Всего: 404 сообщения
|
Даже не знаю, прав ли я.. или опять глючу :). ---------- procedure set_script_number begin variable V_index; V_index:=C_identify_start; while not(V_index>C_identify_end) do begin if message_str(V_index,C_identify)==obj_name(self_obj) then begin set_local_var(LV_script,V_index); V_index:=C_identify_end+1; end else begin V_index:=V_index+1; end end if local_var(LV_script)==0 then begin display_msg("Error: *.msg file not found for "+obj_name(self_obj)+"."); end else begin display_msg("Соответствующий номер найден: "+local_var(LV_script)+"."); end end ---------- Искомого *.msg файла заранее не существует. Эксперимент #1: ---------- #define C_identify 0 #define C_identify_start 1000 #define C_identify_end 1300 ---------- Результат: после одной-двух секунд раздумий, появляется надпись: "Error: *.msg file not found for Алан." Эксперимент #2: ---------- #define C_identify 0 #define C_identify_start 1000 #define C_identify_end 1400 ---------- Результат: после одной-двух секунд раздумий, Fallout (как и маппер) вылетает с надписью: ".. память не может быть read." Догадываетесь, чего не позволяет нам делать коварная win2k? Объясните, кто догадался :). (Отредактировал(а) Raven - 17:01 - 25 Янв., 2005)
|
Отправлено: 2:39 - 27 Ноября, 2004
|
|
Raven
Пользователь
Откуда: Владик Регистрация: Февр. 2004
Всего: 408 сообщений
|
Посмотри вот это: if message_str(V_index,C_identify) И вот это: #define C_identify 0 Понял, нет? Ты пытаешся читать нулевые строчки в мсг-шках. А строчки там нумеруются от единицы. Понимаешь? Естественно, Фол может вылететь - ведь непонятно в какую область памяти ты лезешь с такими запросами. Вторая потенциальная трабла (вызывающая тормоза :-) - диапазон (1000-1300). Строчки 1-1304 заняты под оригинальные скрипты Фола, поэтом искать в них *свою* мскг-шку бессмысленно. В идеале диапазон должен быть: строчка с первым добавленным тобою скриптом (1305) - последняя строчка в scripts.lst + небольшой запас. >>Догадываетесь, чего не позволяет нам делать коварная win2k? Объясните, кто догадался. Так это - загадка, типа, была - если так, то хорошо :-) P.S. Всю процедуру перебора проще записать так: ------------------------------------------- #define LIM 1500 #define search(line,what) while not message_str(i,line)!=what and i<LIM do i+=1; \ if i==LIM then display_mg(what + " not found") <...> variable i:=1300; search(1,obj_name(self_obj)); set_local_var(0,i); <...> ------------------------------------------- (Добавление от 5:03 - 27 Ноября, 2004.) Наработка номер 2. Проблема: Есть generic-скрипт, определяющий поведение многих объектов сразу (НПС-крестьян в моём случае). Нужно выдавать каждой копии скрипта уникальное имя из списка, чтобы все эти крестьяне были не так безлики. Трабла в том, что так как они являются копиями одного и того же скрипта, то и совпадает у них практически всё - и SID, и имя/описание из scrname.msg, и реакция на talk/description, и данные прототипа... Как быть? Отступление: Полагаю, все знают про импорт/экспорт переменных. Так вот, стандартный метод - это миф. Это недопонимание принципов работы БИСовскими скриптерамИ, перенесённое сюда. Итак, как работает импорт/экспорт. Любая переменная, объявленная как export попадает в некоторый общий namespace - из какого бы скрипта она не экспортировалась. После этого любой другой скрипт может её импортировать. Скрипт карты трогать не нужно. Решение: Всё-таки наши объекты кое-чем различаются - указателями. Вот и воспользуемся этим. -------------------------- //Объявляем набор вар для указателей export variable begin ptr_1; ptr_2; ptr_3; end procedure start begin end procedure map_enter_p_proc begin if not ptr_1 then ptr_1:=self_obj; else if not ptr_2 then ptr_2:=self_obj; else if not ptr_3 then ptr_3:=self_obj; end procedure talk_p_proc begin if self_obj==ptr_1 then display_msg("NPC 1"); else if self_obj==ptr_2 then display_msg("NPC 2"); else if self_obj==ptr_3 then display_msg("NPC 3"); end -------------------------- Фокус в том, что все "внешние" вары хранятся в общем нэймспэйсе и сохраняются/берутся оттуда. Поэтому если мы ставим ptr_1, то для всех остальных объектов, импортировавших (или экспортировавших!) эту вару, она будет уже занята. Это - самый простой (и в плане возможностей, и в плане реализации) вариант. Можно брать имена из msg, сделать его для неограниченного числа НПС с повторениями имён и т.д. Естественно, я описываю идею вообще, не какой-то частный случай. Можно, например, запоминать указатель на последнего чара, говорившего с чузом. А следующий будет справшивать "Я видел, ты там с ... болтал, ну что, как дела у него?".
|
Отправлено: 4:04 - 27 Ноября, 2004
|
|
Alan Killenger
Пользователь
Откуда: Россия, Ижевск Регистрация: Июль 2004
Всего: 404 сообщения
|
Что-то не спешат скриптологи делиться опытом, видать коммерческая ценность . Три эксперимента, которые достаточно явно показывают все, что я знаю о номерах реплик в *.msg файлах:
Цитата:
display_msg(message_str(1304,0)); display_msg(message_str(1304,999)); display_msg(message_str(1304,-998)); display_msg(message_str(1304,998)); display_msg(message_str(1304,-999));
Эксперимент #1.
Цитата:
{0}{}{реплика 0} {999}{}{реплика 999} {-998}{}{реплика -998} {998}{}{реплика 998} {-999}{}{реплика -999}
Цитата:
•реплика 0 •реплика 999 •реплика -998 •реплика 998 •реплика -999
Эксперимент #2.
Цитата:
{0}{}{реплика 0} {999}{}{реплика 999} {-998}{}{реплика -998} #{1.5}{}{реплика 1.5} {998}{}{реплика 998} {-999}{}{реплика -999}
Цитата:
•Error •реплика 999 •реплика -998 •Error •Error
Два раза проверял - именно так. Эксперимент #3.
Цитата:
{0}{}{реплика 0} {999}{}{реплика 999} {-998}{}{реплика -998} #{998}{}{неиспользуемая реплика 998} {998}{}{реплика 998} {-999}{}{реплика -999}
Цитата:
•реплика 0 •реплика 999 •реплика -998 •реплика 998 •реплика -999
P.S. Пошлите кто-нибудь please на мыло любой исходник с использованием таких вещей как spawn или расскажите об этом в "Скриптах". 3.12.04 Выложил работающий скриптик, в котором реализована наработка Raven'а относительно не фиксированных номеров реплик. 4.12.04 Ссылка исправлена. (Отредактировал(а) Alan Killenger - 21:09 - 4 Дек., 2004)
----- hit me, nail me, make me god
|
Отправлено: 20:10 - 29 Ноября, 2004
|
|
Raven
Пользователь
Откуда: Владик Регистрация: Февр. 2004
Всего: 408 сообщений
|
spawn, exec и fork По порядку. Синткаксис: spawn("путь_к_скрипту/файл_скрипта.int"); Запускает скрипт на исполнение (взывает в нём процедуру start). Пока выполняется child-скрипт, родительский простаивает. По прекращению выполнения происходит возврат в исходный скрипт. Т.е. это call для скриптов, а не процедур. exec фнфлогичен spawn, но возвращение происходит только по команде exit. Если она опущена - Фол вылетает. fork - тот же spawn, но вызываемый скрипт работает параллельно основному. Теперь почему это всё нафиг не надо: скрипты, вызванные таким образом, не привязываются к какому-либо объекту (self_obj==0). Естественно, обработчики в них вызваны никогда не будут. И пропадает весь смысл использования скрипта. Кроме того, в вызваном скрипте выполняется только процедура start (хотя можно делать call), по её выполнению скрипт прекраает работу. Пример: ------------------ <...> spawn("scripts/fork.int"); display_msg("back to main"); <...> ------------------ forks.ssl: ------------------ procedure start begin display_msg("spawned script"); end ------------------ Вывод: spawned script back to main (Отредактировал(а) Raven - 10:32 - 30 Ноября, 2004)
|
Отправлено: 3:31 - 30 Ноября, 2004
|
|
Ray
Модератор
Откуда: Донецк,Украина Регистрация: Янв. 2004
Всего: 746 сообщений
|
[deleted] Ой не в тему... Читай ФАК. Там всё описано. WG
|
Отправлено: 15:19 - 5 Дек., 2004
|
|
|
|