» TeamX (Архив Форума)«


Форум TeamX » Исследования » Patroling mode (...или учим NPC ходит по чекпоинтам)

Переход по темам
<< Пред. След. >>
Единственная страница этой темы

 
Raven
Пользователь

Откуда: Владик
Регистрация: Февр. 2004

Всего: 408 сообщений

Кто про что, а я опять про строки и использование msg-файлов в своих корыстных, сугубо скриптерских целях :-)

Наверное, каждый скриптер сталкивался с необходимостью организовать "ходьбу" НПС по маршруту. Лёгкого стандартного метода для этого не существует, приходилось набивать кучу animate_move_to и пользовать timed_event/map_update/critter_p_proc.

Я попытался сделать универсальное решение - с использованием своих любимых строк :-)

Итак, суть. Чего я хотел: возможность легко задавать маршрут любой сложности и с любым количеством чекпоинтов. Желательно, без перекомпиляции.

Как реализовано.

Одна строчка в msg следующего формата:
{n}{}{X|COORD_1|COORD_2|COORD_3|...|COORD_X}
X - число чекпоинтов, COORD_I - координата i-го чекпоинта.

Код. Использую заранее написанную atoimar. Эта процедура получает три параметра - строку-оригинал, строку-стартер и номер ячейки. Возвращает число (int, не str) из указанной ячейки. Разделителем служит символ "|". Строка-стартер - произвольный набор символов до начала массива, он будет отброшен.

Строка-оригинал должна иметь вид:
{n}{}{заголовок:1|2|3|4}
Чтобы получить содержимое второй ячейки, мы должны вызвать её так: atoimar(mstr(n),"заголовок:",1). Цифра "1" - т.к. ячейки нумеруются с нуля.

Код процедуры:
----------------------------------------
procedure atoimar(var ostr, var bstr, var cell) begin
   var i;var val; var str:=""; var c_cell; var j; var flag;
   str:=bstr;
   while c_cell<=cell do begin
       val:=0; flag:=1; j:=0;
       while ((ostr!=str) and (flag)) and j<32 do begin
           while not((ostr>str+i and ostr<str+(i+1)) or ostr==str+i) and i<9 do i+=1;
           if i==9 and ostr>str+"|" and ostr<str+"}" then begin flag:=0; str+="|"; end
           else begin str+=i; val:=val*10+i; end
           j+=1;
           i:=0;
       end
       c_cell+=1;
   end
   return val;
end
----------------------------------------
Если вы разобрались в работе atoi, то поймёте и эту процедуру.

Теперь собственно ходьба по маршруту.

Логика простая. Есть набор мест. Есть текущее место (выносим в глобальную скриптовую переменную). Если мы на месте - выбираем следующую по списку координату и идём туда. Если не на месте (а значит - в движении) - ничего не делаем. Процедура должна постоянно вызывает сама себя, чтобы определить момент прибытия.

Итоговый код:
----------------------------------------
#define var variable


var next_place;

procedure walk;

procedure start begin end

procedure map_enter_p_proc begin
   add_timer_event(self_obj,0,1);
end

procedure walk begin
   var aim_tile; var place_num;

   //получаем общее число чекпоинтом
   place_num:=atoimar(mstr(10),"",0);
   
   //инизиализируем скрипт, стартуем переход к первому чекпоинту
   if not next_place then begin aim_tile:=atoimar(mstr(10),"",1); animate_move_to_tile(aim_tile); next_place:=1; end

   aim_tile:=atoimar(mstr(10),"",next_place);
   
   //выбираем следующий чекпоинт и идём к нему
   if tile_num(self_obj)==aim_tile then begin
       if next_place<place_num then next_place+=1; else next_place:=1;
       aim_tile:=atoimar(mstr(10),"",next_place);
       animate_move_to_tile(aim_tile);
   end

   add_timer_event(self_obj,10,1);
end

procedure timed_event_p_proc begin
   if fixed_param==1 then call walk;
end
----------------------------------------
Тестовая строчка для artemple.map:
{10}{}{4|18494|18888|20292|19898}

Всё. Надеюсь, будет полезным.

Отправлено: 9:12 - 26 Авг., 2005
 

Переход по темам
<< Пред. След. >>
Единственная страница этой темы


Powered by Ikonboard 2.1.9 RUS
Modified by RU.Board Team
© 2000 Ikonboard.com