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


Форум TeamX » Исследования » Metarule

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

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

Откуда: Moscow
Регистрация: Июль 2007

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

найден глюк в работе metarule3(106) aka "tile_get_next_critter".

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

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

по описанию, третья метаруля при 106-м свиче потребляя аргументы (tile, elevation, LastCritter) выдает NextCritter'а. написав:
found:=metarule3((106),tile_num(xxxxx),elevation(dude_obj),0);
мне без проблем удалось добиться нахождения FirstCritter'а на каждом гексе, которого партиец прекрасно находил и обдирал. проблема возникла при попытке обратиться именно к NextCritter'у.

самым простым способом при замысле скрипта, до того, как я уперся в этот глюк, было следующее: найти первого криттера, вынуть из него барахло, проверить, если ли в гексе еще трупы, если есть - уничтожить found'а. что в большой горе кровавого месива стало торчать меньше на одну руку/ногу никто и не заметит, а следующего криттера процедура спокойно найдет на следующей итерации. но!

при написании:
next:=metarule3((106),tile_num(found),elevation(dude_obj),found);
оказалось, что next == found. т.е. получить информацию именно о NextCritter'е, ради которого эта метаруля как будто бы и существует - нет никакой возможности.

очень надеюсь оказаться неправым!!
==================================

к произвольному криттеру можно обратиться на предмет get_critter_stat и т.п., получив доступ к его текущим хитам, стренге, отравленности и т.д. следовательно, криттер - это некоторый массив двордов, из которых 0-й - это стренга, 35-й - это текущие хиты и т.д.
А не является ли 106-й ключ метарули аналогом того механизма, что в криттере, но ссылающимся на дворд, соответствующий "кто стоит в этой клетке", как в криттере было "сколько хитов осталось у этого криттера", с единственной разницей (по задумке, по реализации оказалось что шиш с маслом, если я правильно понял вышеописанный глюк с next и found), что в криттере - это просто какое-то число, а в гексе это число указывает на начало целого списка, потому как в одном гексе может быть навалена дикая куча всякого барахла.

и вопрос: как обратиться к самому тайлу и его содержимому? "содержимому" в смысле как get_critter_stat(self_obj,35) выдаст текущие хиты криттера, или как proto_data(3,14) выдаст цену повер-сьюта, так хочется и чтобы tile_data(xxxxx,1) - выдавала бы указатель на начало списка криттеров, в этом тайле присутствующих.

совсем, наверное, тупой и запредельно наглый вопрос: читая форум я пришел к выводу, что большинство всех компиляторов, декомпиляторов, преобразовалок картинок и т.д. написаны силами самих тим-иксовцев. а если это так, то почему нельзя добавить более универсальные функции, типа той, что я написал абзацем выше (tile_data(xxxxx,1) - начало списка криттеров, tile_data(xxxxx,0) - начало списка предметов, и т.д.), вместо метарулей, которые, во-первых, НЕуниверсальны (ссылки на криттеры получать можно, а на предметы - нет), а, во-вторых, еще и отказываются работать по своему прямому назначению, описанному в define.h

Да простят мне мою наглость, помноженную на некомпетентность, но уж очень хочется!

Отправлено: 15:41 - 22 Июля, 2007
Ray
Модератор

Откуда: Донецк,Украина
Регистрация: Янв. 2004

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

Цитата:
а если это так, то почему нельзя добавить более универсальные функции, типа той, что я написал абзацем выше ...


Дело в том, что как ты функцию не назови, она все равно обрабатывается движком. Фактически в скрипте названия ф-ий не прописаны, а прописаны их опкоды. А по ним уже движёк выполняет некие действия. Соответственно, чтоб добавить универсальные ф-ии нужно править двиг. А так как исходников ни у кого нет то и вопрос закрыт. Были бы исходники - я бы сам с удовольствием

-----
Не бывает невозможных задач – бывает мало времени.

Отправлено: 0:48 - 23 Июля, 2007
JSilver
Пользователь

Откуда: Moscow
Регистрация: Июль 2007

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

подожди. ты хочешь сказать, что сами бисовцы, делая свой движок и все остальное, обращались к своим структурам не как белые люди типа array1[x,y].field1 и array2[z].field555, а написали отдельные "специальные" функции, в которых эти x,y и z были зашиты намертво?? и если к какому-нибудь полю типа текущих хитов функция доступа существует, то ее и каждый мододел теперь может использовать, а к какому-нибудь другому - не существует, то есть единственный к нему доступ, который называется hex-editor, ну а он имеет такую вредную тенденцию работать вне игрушки а не В ней.

=======
по самой метаруле: у меня точно не глюк? 106-й ключ действительно не работает? точнее работает, но не полностью.

Отправлено: 11:06 - 23 Июля, 2007
Tehnokrat
Модератор

Откуда: Новосибирск
Регистрация: Окт. 2003

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

Цитата:
и если к какому-нибудь полю типа текущих хитов функция доступа существует, то ее и каждый мододел теперь может использовать, а к какому-нибудь другому - не существует, то есть единственный к нему доступ, который называется hex-editor, ну а он имеет такую вредную тенденцию работать вне игрушки а не В ней.

Вот именно. Функцию из скрипта компиль переводит в опкод, который получает двиг при исполнении скрипта. Затем вызывается процедура, соответствующая данному опкоду и вытаскивает из скрипта параметры функции. И только потом вызывается процедура, отвечающая за данное действие. Можно изменить существующие скриптовые функции, теоретически можно даже новые добавлять, но процесс настолько трудоёмкий, что связываться с этим никто не будет.

Цитата:
по самой метаруле: у меня точно не глюк? 106-й ключ действительно не работает? точнее работает, но не полностью.

Подтверждаю. Эта метаруль не исполняет взятых на себя обязательств и не возвращает указатель на следующего криттера по указателю на предыдущего. Единственное, что могу порекомендовать - выкидывай осмотренные трупаки на соседний гекс и ищи обратно "found:=metarule3((106),tile_num(xxxxx),elevation(dude_obj),0);" пока трупаки не кончатся.

-----
Прошлое можно узнать, но нельзя изменить. Будущее можно изменить, но нельзя узнать.

Отправлено: 23:33 - 23 Июля, 2007
JSilver
Пользователь

Откуда: Moscow
Регистрация: Июль 2007

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

Итак, что имеем в результате (найдено: JSilver; подтверждено: Ray, Tehnokrat):

metarule3(106, tile, elev, lastcritter) можно использовать только для нахождения самого первого криттера в гексе, т.е. вызовом metarule3(106, tile, elev, 0), и большего от нее добиться нельзя.
В таком виде ее все таки можно использовать, ибо для доступа к следующему, если он там есть, можно дополнительно использовать move_to или destroy_object, которые этот гекс освобождают.

Примером использования этой возможности является процедура обхода криттером трупов после боя и изъятия у них инвентаря.

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

Небольшим недостатком ее является тот факт, что по какой-то странной причине, которую я склонен понимать как "валяющийся труп занимает больше одного гекса и может быть "найден" на любом из них", труп, будучи освобожденным от своего инвентаря, возвращается не строго на то же самое место где валялся ранее, а плюс-минус один гекс в любую сторону. Соответственно, при неудачном возвращении он может накрыть собой ЕЩЕ НЕ ободранный труп, который при этом может стать недоступным. Таким образом собирание 100% вещей со 100% трупов происходит НЕ в 100% случаев. Но, тем не менее, поскольку эта процедура все же позволяет собирать больше вещей, чем их обычно может собрать после боя сам приключенец если ронял трупы один на другой, и происходит без его участия - партиец сам все делает если находится в режиме "сбора вещей", то в целом процедурка приятная.

Если кому-то надо - могу выложить соответствующий кусок кода, скажите только куда именно - сюда ли, в скрипты ли или еще куда.

Отправлено: 11:08 - 24 Июля, 2007
Jordan 63
Пользователь

Откуда: Россия, Самара
Регистрация: Июль 2007

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

JSilver
Если кому-то надо - могу выложить соответствующий кусок кода, скажите только куда именно - сюда ли, в скрипты ли или еще куда.

Сюда выкладывай.

Отправлено: 12:37 - 24 Июля, 2007
JSilver
Пользователь

Откуда: Moscow
Регистрация: Июль 2007

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

procedure loot_critter (variable R, variable stage) begin
variable elev;
variable tile;
variable next;
 elev:=elevation(dude_obj);
 if (stage==0) then
   begin
     FoundObj:=find_critter(R,dude_tile,elev);
       if (FoundObj>0) then
         begin
           set_looting(1);
           if (tile_distance(self_tile,tile_num(FoundObj)) < 7)
             then animate_move_to_tile(tile_num(FoundObj));
             else animate_run_to_tile(tile_num(FoundObj));
         end
   end
 else if (stage==1) then
   begin
     tile:=tile_num(FoundObj);
     if (tile_distance(self_tile,tile)<=2)
       then
         begin
           tile:=tile_num(FoundObj);
           move_obj_inven_to_obj(FoundObj,self_obj);
           move_to(FoundObj,0,elev);
           next:=metarule3((106),tile,elev,0);
           if (next>0)
             then
               begin
                 if ( (obj_type(next)==1) and (critter_state(next) == CRITTER_IS_DEAD) )
                   then
                     begin
                       destroy_object(FoundObj);
                       FoundObj:=next;
                     end
                   else
                     begin
                       move_to(FoundObj,tile,elev);
                       set_looting(2);
                       FoundObj:=0;
                     end
               end
             else
               begin
                 move_to(FoundObj,tile,elev);
                 set_looting(2);
                 FoundObj:=0;
               end
         end
   end
end

procedure find_critter (variable R, variable base, variable elev) begin
variable begin
found:=0;
ok:=0;
i;j;d;tile;
end
 i:=R+1;
 while ((i>-r) and (ok==0)) do
   begin
     i:=i-1;
     d:=(r-i)*2;
     if i>0 then d:=d+1;
     j:=d+1;
     while ((j>-d) and (ok==0)) do
       begin
         j:=j-1;
         tile:=base+200*i+j;
         if (tile_distance(tile,base)<=r) then
           begin
             found:=metarule3((106),tile,elev,0);
             if (found>0) then
               if ((found != dude_obj) and (found != self_obj)) then
                 if (critter_state(found) == CRITTER_IS_DEAD) then
                   if (inven_count(found)>0)
                     then ok:=1;
           end
       end
   end
 return found;
end

Отправлено: 18:01 - 29 Июля, 2007
Wasteland Ghost
Маленькое Злое Привидение

Откуда: Россия, Самара
Регистрация: Дек. 2002

Всего: 2251 сообщение

Цитата:
Полезность ее может оценить всякий, кто после драки обдирал трупы врагов и тихо матерился по поводу того, что "он точно знает, что в этой кровавой луже лежат как минимум трое, но вот он уже пятый раз пытается ткнуть в нее мышой и пятый раз снова попадает в один и тот же труп, который валяется верхним"

На стрелочки под портретом трупа в инвентаре никогда внимания не обращал?

Отправлено: 12:08 - 2 Авг., 2007
JSilver
Пользователь

Откуда: Moscow
Регистрация: Июль 2007

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

Цитата:
На стрелочки под портретом трупа в инвентаре никогда внимания не обращал?

блин, стыдно то каааак.... ведь действительно не обращал же. я, наверное, настолько часто одиночные трупешники кладу, а у них как раз стрелочки не видны, что когда у множественного трупа они появляются - я просто не успеваю обратить на них внимание.
НО! что характерно! я уверен, что именно на этих стрелочках эта 106 метаруля и должна работать, причем именно так, как задокументировано, т.е. давать СЛЕДУЮЩЕГО криттера, а не только первого. раз есть такие стрелки и именно такая функция, а других функций (на предметы, например) нету - то мне думается, что она именно для них и прописана. я прав?

Отправлено: 3:02 - 5 Авг., 2007
Ray
Модератор

Откуда: Донецк,Украина
Регистрация: Янв. 2004

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

Цитата:
я прав?


Нет, не прав. Движёк не использует скрипты кроме как по прямому их назначению. Может это и не правильно, но я ничего подобного в двиге не замечал. Покрайней мере ф-ия обрабатывающая metarule нигде больше не вызывается.

-----
Не бывает невозможных задач – бывает мало времени.

Отправлено: 11:48 - 5 Авг., 2007
 

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


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