|
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
|
|
|
|