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


Форум TeamX » Тех. поддержка » Скрипты (Все вопросы по скриптингу - сюда)

Переход по темам
<< Пред. След. >>
Страницы этой темы [ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 ] Все собщения

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

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

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

to Garold

По поводу битов: молодец, растёшь. :-)

Я использовал битовую запись в LVARы при написании скрипта игры в пятикарточный покер на троих. В 6 LVAR-ов удалось запихнуть почти 100 переменных - информацию о наличии/отсутствии в колоде каждой из 52 карт, информацию о картах на руках у каждого из трёх игроков, информацию о наличии комбинаций у текущего игрока.

Возможно, ты видел мой постинг с вопросом о структуре save-файлов. Мы с Абелем продолжили разговор по почте. И буквально два дня назад я предложил ему идею побитовой записи в неиспользованные в игре, но прописанные в vault13.gam GVARы. В три GVARы можно записать 90 битовых (1/0) значений, т.е. информацию о 45-ти небольших простых квестах (1/0 - взят/не взят, 1/0 - выполнен/не выполнен). Для квестов с многочисленными исходами или временным лимитом потребуеться, конечно, больше битов - но ведь и свободных GVARов, если поискать, можно найти побольше.

Причём тут сейвы? Дело в том, что при добавлении нового квеста (и, соответственно, новых GVARs) в игру необходимо занести GVARы в файл vault13.gam. Все GVARы оттуда пишутся в сейв-файл. И сейвы становятся несовместимыми. Но если мы пишем в вары прописанные в vault13.gam, но не используемые в игре - то сейвы будут совместимы! А побитовая запись позволяет записать в несколько варов большое количество информации. Т.е. если разработать соответствующее API (в виде процедур побитовой записи) и задокументировать соответствующие свободные вары - то можно будет делать полноценные моды, совместимые с сейвами оригинального Фола (а при договорённости между модерами об использовании разных GVARs - и совместимые между собой моды!). Представь себе - выходит новый оружейный мод. Меняет в основном стволы, добавляет квестов, сейвы не совместимы. Что ты будешь делать? Начинать играть по новой? А так - загрузил свой СТАРЫЙ сейв и наслаждаешься НОВЫМ оружием и предметами...

Такой подход не потребут перекомпиляции оригинальных скриптов из Фола или подобных трудоёмких операций. Авторы новых модов - возьмите на заметку. К сожалению, реализовать такое в "Новом Взгляде" мы уже не успеем :-( Но "Новый Взгляд" как раз и предполагает пролхождение игры с самого начала.

Теперь, по традиции, полезная часть. Два куска кода из моего покера с реализацией побитовой записи/чтения (я использовал LVAR, а не GVAR - но никакой разницы, как понимаете, нет). О-о-чень рекомендую уж если не изучить код - то ознакомиться с комментариями.

----poker_bits.ssl----
//Работа с битовыми массивами ( в смысле, с LVARS :-)

//Возвращает 1/0 - есть/нет карта с UID x (1-52) в колоде
//Возвращат значение бита x из одной из двух пременных, отведённых под колоду
procedure get_deck(variable x) begin
  if (x < 31) then return lvar_bit(LV_DECK1,pow(2,x-1));
  else return lvar_bit(LV_DECK2,pow(2,x-31));
end

/*
lvar_bit(x,2^y) - возвращает значение бита номер y из переменной x
Для использования процедуры очень желательна ф-ия возведения в степень
pow(x,y) - возвращает x^y
*/

<...>

//Для работы с .. гм .. руками.
//Процедура записывает число от 1 до 52 в переменную hand (hand хранит значение LVAR руки текущего игрока)
//для представления числа 52 необходимо 6 бит, т.е. в переменную записывается пять блоков по 6 бит
//num определят смещение tmp для записи значения карты номер num (1-5)
//---------------------------------------------------
procedure set_hand(variable num,variable value) begin
  variable i:=5;variable tmp;variable tmp1:=32;
  tmp:=6*num-1;//6*(num-1)+(5-i);
  while i>=0 do begin
     if value/tmp1!=0 then begin
        set_lvar_bit_on(hand,pow(2,tmp-i));
        value-=tmp1;
     end else set_lvar_bit_off(hand,pow(2,tmp-i));
     tmp1/=2;
     i-=1;
  end
end

/*
to Garold
Принцип работы процедуры set_hand на примере.
Пусть мы хотим записать в hand информацию о том, что карта номер 4 в руке имеет номер 51.
num:=4;value:=51;tmp1:=32;
tmp:=23;
Первый проход цикла:
Срабатывает условие if (51 больше-равно 32) - мы устанавливаем бит номер tmp-i=23-5=18 - первый в 4-ом 6-и битовом блоке.
value=51-32=19
tmp1:=tmp1/2=16;
i:=4;
Второй проход:
if (19 больше-равно 16) == true => устанавливаем второй бит в блоке
value:=3;tmp1:=8;i:=3;
Третий проход:
if ( 3 больше-равно 8 ) == false => третий бит в 0
value:=3;tmp1:=4;i:=2;
Четвёртый проход:
if ( 3 больше-равно 4 ) == false => четвёртый бит в 0
value:=3;tmp1:=2;i:=1;
Пятый проход:
if ( 3 больше-равно 2 ) == true => пятый бит в 1
value:=3-2=1;tmp1:=1;i:=0;
Шестой проход:
if ( 1 больше-равно 1 ) == true => шестой бит в 1

В конечном итоге имеем запись 110011 - двоичное значение 51 (вообще говоря, "перевёрнутое") со смещения 18-1=17
В принципе, стандартнаz процедура конвертации dec->bin, только bin записывается задом наперёд
*/

//Разбери сам (лучше на примере).
procedure get_hand(variable num) begin
  variable i:=0;variable tmp:=0;
  variable tmp1;variable tmp2:=1;
  tmp1:=6*num-1;
  while (i<=5) do begin
     if lvar_bit(hand,pow(2,tmp1-i)) then tmp+=tmp2;
     tmp2*=2;
     i+=1;
  end
  return tmp;
end

<...>
----poker_bits.ssl----

Листинг процедуры pow(x,y)
--------
//возведение в степень. x - показатель, y - степень
procedure pow(variable x,variable y) begin
/*
Степени разбиты по категориям для ускорения, т.к. при линейной структуре процедура возврата
работает ОЧЕНЬ медленно, не говоря уже об универсальном возведении в степень (см. конец процедуры)
*/

  variable i:=1;variable tmp;
  if y==1 then return x;
  if y==0 then return 1;
  if y==-1 then return (1/x);

//Ускоряем возврат степеней двойки. Вплоть до 2^30
//на 2^31 наступает переполнение, мы можем писать/читать только 30 бит в варе
  if (x==2 and y < 31) then begin

     if (y<10) then
     if (y<6) then begin
        if (y==2) then return 4;
        if (y==3) then return 8;
        if (y==4) then return 16;
        if (y==5) then return 32;
     end else begin
        if (y==6) then return 64;
        if (y==7) then return 128;
        if (y==8) then return 256;
        if (y==9) then return 512;
     end

     if (y<20) then
     if (y<16) then begin
        if (y<13) then begin
           if (y == 10) then return 1024;
           if (y == 11) then return 2048;
           if (y == 12) then return 4096;
        end else begin
           if (y == 13) then return 8192;
           if (y == 14) then return 16384;
           if (y == 15) then return 32768;
        end
     end else begin
        if (y == 16) then return 65536;
        if (y == 17) then return 131072;
        if (y == 18) then return 262144;
        if (y == 19) then return 524288;
     end

     if (y<31) then
     if (y<26) then begin
        if (y<23) then begin
           if (y == 20) then return 1048576;
           if (y == 21) then return 2097152;
           if (y == 22) then return 4194304;
        end else begin
           if (y == 23) then return 8388608;
           if (y == 24) then return 16777216;
           if (y == 25) then return 33554432;
        end
     end else begin
        if (y == 26) then return 67108864;
        if (y == 27) then return 134217728;
        if (y == 28) then return 268435456;
        if (y == 29) then return 536870912;
        if (y == 30) then return 1073741824;
     end
  end
  tmp:=x;
  if y>1 then begin
     while(i<y) do begin tmp*=x;i+=1; end
     return tmp;
  end
  if y<0 then begin
     while(i<=0-y+1) do begin tmp*=x;i+=1; end
  return (1/tmp);
  end
end
--------

to Garold
Если нужен скрипт Покера - пиши на мыло.

(Отредактировал(а) Raven - 13:19 - 30 Апр., 2004)

Отправлено: 6:14 - 30 Апр., 2004
Jo Jim
Пользователь

Регистрация: Март 2004

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

А если без "наверное".
Тут, я так понимаю, отвечают на вопросы новичков.
Ничего сложного я не спросил, а ответа так и не получил
Итак, где можно посмотреть, какими значениями инициализируются LVAR для определенного скрипта.
Пример:
dclara.ssl
Какие значения у переменных
LVAR_Home_Tile
LVAR_Home_Rotation

Отправлено: 10:32 - 30 Апр., 2004
Raven
Пользователь

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

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

to Jo Jim

Извини за задержку :-)

Если явной инициализации нет, то смотри все вызываемые в скрипте макросы (в процедурах start, map_enter, timed_event, critter_p_proc и т.п.) - LVAR инициализируется в одном из них. Т.к. в Фолаутовских скриптах вложенность макросов велика (один макрос может быть надстройкой для другого, который построен на базе третьего и т.д.), то найти точное место инициализации довольно сложно.

Для твоего примера. dclara.ssl = Den Critter Lara
Следовательно, критер "прописан" в Дэне. Открываем
headers\den.h
, ищем строчку
set_local_var(LVAR_Home_Tile
Находим строчку в макросе gang_member_map_enter
Теперь открываем скрипт Лары и ищем gang_member_map_enter:
-------------------
procedure map_enter_p_proc begin
  gang_member_map_enter
  flush_add_timer_event_sec(self_obj, 1, timed_event_float);
end
-------------------
Т.е. вара LVAR_Home_Tile инициализируется каждый раз при заходе на карту. Там же инициализируется LVAR_Home_Rotation.

Вообще говоря, макрос не обязательно будет именно в имя_города.h, лучше делать контекстный поиск по всем файлам в headers.

to Gatling
А ты пробовал пользовать VDM?

Отправлено: 12:28 - 30 Апр., 2004
Jo Jim
Пользователь

Регистрация: Март 2004

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

Спасибо, Рэйвен.
Очень полезная информация оказалась, но я по- прежнему не могу найти ЗНАЧЕНИЯ которыми, скажем так, заполняются эти переменные.
Опишу ситуацию подробнее.
После уничтожения банды Тайлера и выхода и боевого режима банда Лары занимает церковь.
В версии 1.0 (и в бисовских скриптах) Лара встает на место Тайлера, справа от входа в церковь. В Версии 1.2 Лара располагается внутри церкви вместе со своей бандой.
В связи с эти у меня проблема: Действуя по описанной технолонгии, я по-прежнему не могу получить конкретно set_local_var(LVAR_Home_Tile, 23096), например. То есть я не знаю где именно  эти значения и чему эти значения, извините за такое выражание, равны! Ведь для каждого скрипта каждого члена банды долже быть свой LVAR - то есть где-то должно быть систематизированное хранилище этих значений.

Отправлено: 15:34 - 30 Апр., 2004
GaroldPredator
Пользователь

Откуда: Military Base
Регистрация: Апр. 2004

Всего: 52 сообщения

to Gatling
Лично я леплю диалоги прямо в f-Gecke (где найти его, смотри в начале), а чтобы не запутаться, перед каждой процедурой добавляю комментарии!
vsem ostalьnыm
Я собственно зачем пришёл?
Ах, да, хочу спросить!
Я добавил несколько скриптов (XSCOMP.INT, XSCOMP1.INT, XSCOMP2.INT), причём XSCOMP2.INT последний.
Когда я пытаюсь привязать эти скрипты к объектам, привязывается почему-то только последний!
Если в списке выбора скриптов тыкать первый или второй, всё равно выбирается последний!!!
Что делать?!

(Отредактировал(а) GaroldPredator - 17:41 - 30 Апр., 2004)

-----
В мире есть две точки зрения: неправильная и моя.

Отправлено: 17:39 - 30 Апр., 2004
Raven
Пользователь

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

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

to Garold

Посмотри наличие/отсутствие в Scripts.lst пустых строк. Поменяй табы на пробелы во всех самостоятельно вписанных строках. Просмотри scripts.lst в различных текстовых редакторах.

Т.е. проблема возникает из-за несоблюдения формата scripts.lst

to Jo Jim

Ответ уже готов. В голове. Перевожу в текстовый формат - как закончу - сделаю пост.

Отправлено: 3:25 - 1 Мая, 2004
Raven
Пользователь

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

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

to Jo Jim

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

Итак, мы ищем координаты хексов на которые встают члены банды Лары после боя с бандой Тайлера.
Начнём с начала. Ищем в dclara.msg номер строки, начинающей атаку на Тайлера:

---dclara.msg line:158---
{490}{}{I don't think so. You'll have to come with us if you want your money. You
won't have to fight but just to be sure it's not a trap. We'll give you $300 total.}
{491}{}{You ready?}
{492}{}{Okay, let's do it.}       <--- То, что нам надо.
-------------------------

Ищем номер 492 в dclara.ssl:

---dclara.ssl line:450---
NOption(492, Node990, 004);
-------------------------

Ищем Node990:

---dclara.ssl line:277---
procedure Node990 begin
  setup_gang_fight;
end
-------------------------

Открываем den.h и изучаем макрос setup_gang_fight:

---den.h line:583---
<...>
set_gangwar(state_gangwar_in_fight); <--- устанавливает GVAR_DEN_GANGWAR=state_gangwar_in_fight
<...>
load_map(MAP_DEN_BUSINESS,0) <--- грузим карту denbus2.map (см.
--------------------

Открываем maps\denbus2.ssl и видим следующее:

---denbus2.ssl line:58---
procedure map_enter_p_proc begin
<...>
  if (gangwar(state_gangwar_in_fight)) then begin
     override_map_start_hex(21945,0,2); <--- закидываем Чузена поближе к церкви
<...>
-------------------------

Одновременно у всех критеров из банды Лары срабатывает map_enter_p_proc. Это просто вызов макроса  gang_member_map_enter из den.h. Смотрим только те ветки if-ов, которые срабатывают для gang2, т.к. у Лары в скрипте написано
#define self_gang                         gang_2

Итак, смотрим:

---den.h line:798---
<...>
end else if (self_gang == gang_2) then begin
  if (NAME == SCRIPT_DCLARA) then gang_2_member_1 := self_obj;
<...>
  end
--------------------

Здесь переменные вида gang_x_member_y заполняются указателями на членов банд. Для Лары и Марка всегда y:=1, для остальных - как придётся. Эти вары импортируются в скрипте Лары и остальных критеров (про импорт/экспорт можешь прочесть в моём предыдущем посте. Если не поймёшь - спрашивай, объясню подробнее).

Дальше:

---den.h line:798---
<...>
  end if (gangwar(state_gangwar_in_fight)) then begin
     <...>      
     end else if (self_gang == gang_2) then begin
         if (gang_trap(state_gang_trap_no)) then begin
             critter_add_trait(self_obj,TRAIT_OBJECT,OBJECT_TEAM_NUM,TEAM_PLAYER);
<...>
--------------------

Лара загоняется в команду к игроку. Теперь смотрим gang_critter_p_proc:

---den.h line:777---
<...>
 if (gangwar(state_gangwar_in_fight)) then begin
    if (self_gang == gang_2) then begin
       gang_2_follow_to_attack
<...>
--------------------

Смотрим gang_2_follow_to_attack -> set_gang_2_follow - видим, что каждому мемберу Лариной банде приказывается долбить мембера опозиционной банды с минимальным номером (начиная с Марка, для которого, как помнишь x:=1). Начинается резня. При убийстве членов gang1 срабатывает dest_gang_member, который обнуляет указатель gang_1_member_x и вызывает dec_gang_counter(self_gang). Когда банда перебита, срабатывает set_gang_1_dead -> set_gangwar(state_gangwar_2won).

Всё - война закончилась, Лара победила, все указатели на gang_1_member_x обнулены.

Теперь, собственно, ответ на твой вопрос :-)

Смотрим gang_map_update_p_proc:

---den.h line:863---
if (local_var(LVAR_Home_Tile) == 0) then begin
  if (self_gang == gang_2) then begin
     check_take_home_tile(1)
     else check_take_home_tile(2)
     else check_take_home_tile(3)
     else check_take_home_tile(4)
     else check_take_home_tile(5)
     if (local_var(LVAR_Home_Tile) == 0) then begin
        random_tile_in_box(22340, 22332, 24132, 23940);
        set_local_var(LVAR_Home_Tile, global_temp);
        set_local_var(LVAR_Home_Rotation, random(2,4));
     end
  end else begin
     set_local_var(LVAR_Home_Tile, self_tile);
  end
end
--------------------

check_take_home_tile(x) устанавливает LVAR_Home_Tile мембера Лариной банды номер x равному текущему положению соответствующего по номеру мембера банды Тайлера. Когда бой закончен - check_take_home_tile перестаёт работать, а переменным

LVAR_Home_Tile присваивается случайное значение из квадрата с координатами (22340, 22332, 24132, 23940)

LVAR_Home_Rotation присваивается случайное значение от 2 до 4 включительно.

После установки этих значений критер идёт куда надо и поворачивается благодаря следующим строчкам из gang_critter_p_proc:

---den.h line:777---
<...>
end else if (self_tile != local_var(LVAR_Home_Tile)) then begin
  animate_move_to_tile(local_var(LVAR_Home_Tile));
end else if (self_cur_rot != local_var(LVAR_Home_Rotation)) then begin
  animate_rotation(local_var(LVAR_Home_Rotation));
end  
--------------------


Отправлено: 8:14 - 1 Мая, 2004
GaroldPredator
Пользователь

Откуда: Military Base
Регистрация: Апр. 2004

Всего: 52 сообщения

Спасибо, конечно, но я забыл написать, что уже разобрался !

-----
В мире есть две точки зрения: неправильная и моя.

Отправлено: 9:24 - 1 Мая, 2004
GaroldPredator
Пользователь

Откуда: Military Base
Регистрация: Апр. 2004

Всего: 52 сообщения

to Raven
Меня давно мучает такой вопрос:
Как воспроизвести анимацию, не используя объект? Т.е, я использую компьютер, и из-за этого где-то открывается дверь.
И второй вопрос вдогон:
Я нарисовал анимацию опсукания шлагбаума (такого, как в Военной базе). Как мне её привязать к этому шлагбауму.
Шлагбаум в закрытом положении. Я использую комп. Вызывается анимация поднимания (или поднятия?) шлагбаума. Шлагбаум в поднятом положении.
Как всё это провернуть?

-----
В мире есть две точки зрения: неправильная и моя.

Отправлено: 17:34 - 1 Мая, 2004
Raven
Пользователь

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

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

Для воспроизведения произвольной анимации используй команду
----------------------------------------------------------
#include <animcomd.h>
anim(obj_ptr,anim_index,direction);
----------------------------------------------------------
,где obj_ptr -указатель на анимируемый объект, anim_index - из списка ANIM_ в animcomd.h, direction - 0-5

Это работает, в основном, для критеров. Для твоего случая этого не надо. Более того, простое проигрывание анимации открытия двери не сделает эту дверь открытой - ты получишь закрытую дверь с анимацией "открытой" двери.
Для это лучше использовать процедуру
----------------------------------------------------------
obj_open(obj_ptr);
----------------------------------------------------------
Для получения указателя на дверь можно использовать импорт переменных. Но не нужно. Лучше:
----------------------------------------------------------
tile_contains_pid_obj(int tile, int elev, int pid);
----------------------------------------------------------
Tile - координата двери. Берёшь из Мапера - просто выбери дверь и запомни пятизначное число в левом нижнем углу. Elevation - без комментариев. С pid`ом сложнее. Можешь написать простенький скриптик:
----------------------------------------------------------
procedure look_at_p_proc begin
 display_msg("PID:"+obj_pid(self_obj);
end
----------------------------------------------------------
и повесить на дверь (или что у тебя там). Если ты настроил Мапер на редактирование прототипов - то можешь просто выбрать прото своей двери, нажать E, поменять что-нибудь и сразу вернуть изменения, нажать Done. Теперь в C:\Fallout2\dev\proto\scenery у тебя появится что-то типа 00000022.txt и в нём будет указана разная информация об объекте - в т.ч. и pid.

В конечном итоге у тебя получится что-то подобное:
----------------------------------------------------------
obj_open(tile_contains_pid_obj(20301,0,33554454));
----------------------------------------------------------
Прописываешь это в нужном ноде или use_p_proc - и всё.

Второй вопрос: тебе нужно заделать шлагбаум под дверь и сопоставить стандартным frm-кам двери твои анимации (открыт, закрывается, закрыт;открывается = закрывается наоборот, ей рисовать не надо). Т.е., насколько я понял, у тебя есть три frm-ки? Одна анимированная и две статичных? Расскажи, пожалуйста, поподробнее.

Отправлено: 5:59 - 2 Мая, 2004
 

Переход по темам
<< Пред. След. >>
Страницы этой темы [ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 ] Все собщения


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