You are not logged in.
{$CLEO} 0AC6: 0@ = label @lbl offset 0A8C: write_memory 0x00469E2C size 4 value 0@ virtual_protect 1 0AC7: 1@ = var 31@ offset 0@ += 2 0A8C: write_memory 0@ size 4 value 1@ virtual_protect 0 while true wait 0 {if 0AB0: key_pressed 0x73 then 0112: wasted_or_busted // mission only if 31@ == 1 then Player.Money($PLAYER_CHAR) += 1 31@ = 0 end end} end // 0A93: end_custom_thread :lbl hex C705 00000000 01000000 // MOV DWORD PTR DS:[00000000], 1 B8 9B9A4600 // MOV EAX,00469A9B FFE0 // JMP EAX end
@Sergey81 - ну, как вариант:
0A8C: write_memory 0x0061907A size 4 value 0x90909090 virtual_protect 1 0A8C: write_memory 0x0061907E size 1 value 0x90 virtual_protect 1
Last edited by Sanchez (01-10-2010 06:32)
Offline
@Sanchez - по условиям задачи опкоды CLEO 4 использовать нельзя.
За асм спасибо)
Использование 0112 в цикле - это только для тестирования? Просто получается излишнее дублирование, т.к. асм сам прыгнет на него.
В общем, перехватчик опкода 0112 будет выглядеть как-то так:
{$CLEO} 0A9F: 0@ = current_thread_pointer 0A8E: 10@ = 0@ + 0x10 0A8D: 10@ = read_memory 10@ size 4 virtual_protect 0 0A8F: 11@ = 10@ - @lbl 0A8C: write_memory 0x00469E2C size 4 value 11@ virtual_protect 1 0@ += 0x40 // 0@ = 1@'s global address; fixed 02/10/10 11@ += 2 0A8C: write_memory 11@ size 4 value 0@ virtual_protect 0 while true wait 0 if 1@ == 1 then //здесь можно делать автосохранение 1@ = 0 end end :lbl hex C705 00000000 01000000 // MOV DWORD PTR DS:[00000000], 1 B8 9B9A4600 // MOV EAX,00469A9B FFE0 // JMP EAX end
Last edited by Seemann (02-10-2010 19:26)
Offline
Блин, нет пока возможности детально всё проверить, но быстрая проверка показала что автосейв не срабатывает. После then прописывал вызов функции и ничего. Кстати, если мы делаем автосейв до использования опкода, который используется только в миссиях, не получается ли так, что сейв делается во время миссии?
Offline
Кстати, если мы делаем автосейв до использования опкода, который используется только в миссиях, не получается ли так, что сейв делается во время миссии?
да, верное замечание. тогда нужно после проверки 1@ в цикле проверять состояние ONMISSION == 0.
Offline
Снова ничего, запустил миссию, провалил её(c выполнением пробовал, но так быстрее):
********************************************
thread AutoSav
Local variables dump:
52497188 0 1 0 0 0 0 0 0 0 52497620 52497771 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
********************************************
00000084: 00D6
get numeric params: 1
param 1 = 1
00000088: 0039
get numeric params: 1
param 1 = 1
00000095: 0038
get numeric params: 1
param 1 = 0
00000102: 004D (&IFresult = False)
get numeric params: 1
param 1 = -142 (&label: 0002)
00000142: 0002
get numeric params: 1
param 1 = -80 (&label: 0001)
00000080: 0001
get numeric params: 1
param 1 = 0
Offline
Вы пока проверяете только тот факт, что опкод был когда-либо за все время действия миссии вызван - а он вызывается постоянно. Нужно проверять, что этот опкод устанавливает результат логической операции True. Следовательно, втыкаться надо в адрес 00469B0Eh и проверять результат логической операции обрабатываемого потока.
Все прыжки в x86 относительные - то есть выполняются примерно так:
eip := eip + /imm32
Значение instruction pointer при обработке текущей инструкции - 00469B13h. То есть из адреса метки надо вычесть это число и записать по адресу 00469B0Fh (virtual protect - 1). В asm-обработчике проверяем значение byte ptr [esi+C5h] на "не ноль" и в зависимости от этого пишем в 0@ единицу или ноль.
Last edited by Alien (02-10-2010 09:38)
Offline
Вообще то опкод 0112 вызывается только один раз. В ходе миссии автоматически проверяется состояние игрока (wasted/busted) и, если его поймали или он умер, автоматически осуществляется возврат из всех gosub. Поскольку тело миссии - это тоже gosub мы приходим к опкоду 0112
:CASINO6 03A4: name_thread 'CASINO6' 0050: gosub @CASINO6_47 00D6: if 0112: wasted_or_busted // mission only
@Sergey81 - нужно смотреть что творится в нашем асме через отладчик. Ставить брейкпойнт и проверять, срабатывает код и записывает ли куда нужно 1.
Last edited by Seemann (02-10-2010 11:36)
Offline
Ну хорошо, пусть он вызывается 1 раз. Но в чем смысл отслеживания 0112? Чтобы засечь окончание миссии как таковое или чтобы проверить, провалилась она или прошла успешно? И то, и другое решается без всяких асмов. Для первого варианта нужно постоянно синхронизироваться с ONMISSION, для второго достаточно отследить изменение либо стата количества успешно пройденных миссий, либо gxt последней пройденной миссии.
Первый вариант:
{$CLEO} wait 0 while true while $ONMISSION == 0 wait 0 end while $ONMISSION == 1 wait 0 end // тут сохраняемся end
Для второго варианта:
{$CLEO} wait 0 while true wait 0 0652: 0@ = integer_stat 147 repeat wait 0 0652: 1@ = integer_stat 147 until 1@ <> 0@ while $ONMISSION <> 0 wait 0 end // тут сохраняемся end
Offline
{$CLEO} 31@ = 0 0AC6: 0@ = label @lbl offset 0A8C: write_memory 0x469E2C size 4 value 0@ virtual_protect 1 0AC7: 1@ = var 31@ offset 0@ += 2 0A8C: write_memory 0@ size 4 value 1@ virtual_protect 0 while true wait 0 if 31@ == 1 then while true wait 0 if and $ONMISSION == 0 not Actor.Driving($PLAYER_ACTOR) then Break end end 0AA5: call 0x619060 num_params 1 pop 0 2 0ACE: show_formatted_text_box "SAVE OK" 31@ = 0 end end :lbl hex C705 00000000 01000000 // MOV DWORD PTR DS:[00000000], 1 B8 9B9A4600 // MOV EAX,00469A9B FFE0 // JMP EAX end
Проверил все работает. Осталось добавить различных проверок:
0256: player $PLAYER_CHAR defined 0AA9: is_game_version_original
Last edited by Sanchez (02-10-2010 13:57)
Offline
Резюмирую:
Код Alien'а с integer_stat 147 работает, его пока добавил в тему мода в качестве беты2.
Код Sanchez'а из поста выше на CLEO4 работает, но, проверялось на той же миссии с самолётом, после сейва игрок сразу же умирает в воздухе(если автосейв загрузить, игрок в воздухе и не умирает при этом); на CLEO3(взял "шапку" из поста Seemann'а выше) не срабатывает, так что надо там поискать ошибку(для начала переменные поправить).
Ну и 0ACE: show_formatted_text_box "SAVE OK" вроде же не срабатывает во время надписи "Mission Passed"(или другой), так что тут надо как то по другому сделать отображение оповещения(задержку сделать или ещё как-нибудь).
ЗЫ. Проверил ещё раз, с NOP шестичасовой функции из поста 26, работает, время не меняется. В этот раз игрок не умер, но стал глючить скрипт парашюта от ZAZ'а. Впрочем как работает CLEO4 с моими скриптами я уже писал=)
Last edited by Sergey81 (02-10-2010 15:14)
Offline
@Alien - начнем с того, что ONMISSION меняется не только в обычных миссиях, но и реализованных как миссии видеоиграх. После них тоже автосохраняться? Некоторые скрипты также временно устанавливают ONMISSION в 1, чтобы предотвратить запуск миссии. Слишком много ньюансов, поэтому такой топорный способ не подойдет.
К тому же мне это скрипт интересен именно в плане написания перехватчика опкодов. Код, модифицировав который, можно перехватывать, например, создание машин скриптом и манипуляцию с этими машинами.
@Sergey81 - в каком смысле игрок умирает? После срабатывания скрипта сразу смерть? Oo
У Санчеза цикл проверяет 31@ а в шапке моего кода идет речь про 1@. Либо в его коде поставь 1@ либо измени мою шапку. Строка:
0@ += 0x44 // 0@ = 1@'s global address
вычисляет адрес нужной переменной. В 0@ хранится адрес структуры потока. По смещению 0x3C начинаются переменные. Кстати, вот и ошибка. Нужно прибавить не 0x44, а 0x40. Тогда 0@ будет указывать на вторую переменную - 1@.
надо как то по другому сделать отображение оповещения(задержку сделать или ещё как-нибудь).
я бы предложил как в GTA 4 выводить текст в верхнем углу экрана через text_draw. Там же путем плавного изменения координат/цвета текста можно добиться эффекта затухания и титров.
Last edited by Seemann (02-10-2010 19:35)
Offline
@Sergey81 - в каком смысле игрок умирает? После срабатывания скрипта сразу смерть? Oo
На CLEO4 - во время "M_PASS" как будто ударяется о землю с большой высоты и с-но wasted.
На CLEO3 я попробовал переделать, там ещё до "M_PASS", но сейва не происходит.
UPD.
У Санчеза цикл проверяет 31@ а в шапке моего кода идет речь про 1@. Либо в его коде поставь 1@ либо измени мою шапку.
Сделал первым делом, не сохраняло из за 0x44 судя по всему.
{$CLEO} 1@ = 0 0A9F: 0@ = current_thread_pointer 0A8E: 10@ = 0@ + 0x10 0A8D: 10@ = read_memory 10@ size 4 virtual_protect 0 0A8F: 11@ = 10@ - @lbl 0A8C: write_memory 0x00469E2C size 4 value 11@ virtual_protect 1 0@ += 0x40 // 0@ = 1@'s global address; fixed 02/10/10 11@ += 2 0A8C: write_memory 11@ size 4 value 0@ virtual_protect 0 while true wait 0 if 1@ == 1 then while true wait 0 if and $ONMISSION == 0 not Actor.Driving($PLAYER_ACTOR) then Break end end 0AA5: call 0x619060 num_params 1 pop 0 2 // 0ACE: show_formatted_text_box "SAVE OK" 1@ = 0 end end :lbl hex C705 00000000 01000000 // MOV DWORD PTR DS:[00000000], 1 B8 9B9A4600 // MOV EAX,00469A9B FFE0 // JMP EAX end
CLEO3 совместимый код. Оказывается код то я поменял, а cleo.asi нет, на третьей версии всё работает.
Полностью обновлённый код в модификациях.
---
я бы предложил как в GTA 4 выводить текст в верхнем углу экрана через text_draw. Там же путем плавного изменения координат/цвета текста можно добиться эффекта затухания и титров.
Этот текст надо выводить во время надписи Mission Passed, насколько я понял по экспериментам, то пока надпись эта на экране, дополнительно ничего не вывести.
03E5: show_text_box 'AUTOSAV'
звук появления есть, надписи нет.
Оффтоп конечно, но заметил что боты сначала подбегают на близкое расстояние к гг, потом начинают его атаковать из оружия. Было б хорошо если бы они стреляли с любого расстояния.
Ещё можно сделать сохранение sf9.b перед миссией, потом если миссия провалена, предлагать загрузить этот сейв по нажатию кнопки и начинать миссию заново посредством этой загрузки.
Надо только поискать ф-цию загрузки будет.
Last edited by Sergey81 (02-10-2010 20:24)
Offline
Попробуй опкоды
03F0: enable_text_draw 1 033E: set_draw_text_position 320.0 180.333 GXT 'BJ_PUSH'
Кстати, проверка ONMISSION особо не нужна. При срабатывании 0112 наш скрипт неактивен. Игра находится внутри миссии, прыгает временно в асм и возвращается обратно. Поскольку в блоках mission_cleanup нет команды wait, то до самого конца миссии остальные потоки находятся в режиме ожидания. Если 1@ == 1, ONMISSION никогда не будет равна 1 при проверке. Но дополнительная страховка не помешает))
Насчет user interface неплохая идея)) Во-первых, не мешало бы сделать возможность выбрать какой слот использовать для авто-сохранения (ввести комбинацию клавиш, которая будет де-/активировать мод и при активации запрашивать ввод номера слота). Во-вторых, предложенная тобой идея авто-загрузки после провала миссии. Над тем как лучше отслеживать провал миссии еще стоит подумать.
Offline
Попробуй опкоды
03F0: enable_text_draw 1 033E: set_draw_text_position 320.0 180.333 GXT 'BJ_PUSH'Насчет user interface неплохая идея)) Во-первых, не мешало бы сделать возможность выбрать какой слот использовать для авто-сохранения (ввести комбинацию клавиш, которая будет де-/активировать мод и при активации запрашивать ввод номера слота). Во-вторых, предложенная тобой идея авто-загрузки после провала миссии. Над тем как лучше отслеживать провал миссии еще стоит подумать.
Опкоды - если сейв во время "M_PASS"/"M_FAIL", текста не увидел, если после провала слезть с мотоцикла(подождав пока появится остальной худ), в серединке видны буквы, появляющиеся примерно на секунду.
Насчёт номера слота, можно сделать конфиг, туда вписать номер, а в игре комбинациями клавиш или через меню его менять.
Offline
{$CLEO} var 20@ : Integer 21@ : Integer end 0652: 20@ = integer_stat 147 0A8D: 25@ = read_memory 0x0061907A size 4 virtual_protect 1 0A8D: 26@ = read_memory 0x0061907E size 1 virtual_protect 1 1@ = 0 0A9F: 0@ = current_thread_pointer 0A8E: 10@ = 0@ + 0x10 0A8D: 10@ = read_memory 10@ size 4 virtual_protect 0 0A8F: 11@ = 10@ - @lbl 0A8C: write_memory 0x00469E2C size 4 value 11@ virtual_protect 1 0@ += 0x40 // 0@ = 1@'s global address; fixed 02/10/10 11@ += 2 0A8C: write_memory 11@ size 4 value 0@ virtual_protect 0 while true wait 0 if 1@ == 1 then while true wait 0 0652: 21@ = integer_stat 147 if and $ONMISSION == 0 not Actor.Driving($PLAYER_ACTOR) 21@ > 20@ then Break end end 0A8C: write_memory 0x0061907A size 4 value 0x90909090 virtual_protect 1 0A8C: write_memory 0x0061907E size 1 value 0x90 virtual_protect 1 wait 1 0AA5: call 0x619060 num_params 1 pop 0 7 wait 2 0A8C: write_memory 0x0061907A size 4 value 25@ virtual_protect 1 0A8C: write_memory 0x0061907E size 1 value 26@ virtual_protect 1 // 0ACE: show_formatted_text_box "SAVE OK" 1@ = 0 end end :lbl hex C705 00000000 01000000 // MOV DWORD PTR DS:[00000000], 1 B8 9B9A4600 // MOV EAX,00469A9B FFE0 // JMP EAX end
Вот так сделал чтоб не сохранялось при провале миссии. Вроде бы работает. Как раз и идея Алиена пригодилась.
Кстати никто не подскажет как сделать быструю загрузку сейва? А то мне поисками адреса не заняться до следующего воскресенья как минимум.
Ну и проводя аналогию, сейв перед миссией:
{$CLEO} 1@ = 0 0A9F: 0@ = current_thread_pointer 0A8E: 10@ = 0@ + 0x10 0A8D: 10@ = read_memory 10@ size 4 virtual_protect 0 0A8F: 11@ = 10@ - @lbl 0A8C: write_memory 0x0048A244 size 4 value 11@ virtual_protect 1 0@ += 0x40 11@ += 2 0A8C: write_memory 11@ size 4 value 0@ virtual_protect 0 while true wait 0 if 1@ == 1 then while true wait 0 if and $ONMISSION = 0 not Actor.Driving($PLAYER_ACTOR) then Break end end 0AA5: call 0x619060 num_params 1 pop 0 7 1@ = 0 end end :lbl hex C705 00000000 01000000 // MOV DWORD PTR DS:[00000000], 1 B8 21994800 // MOV EAX, 00489921 FFE0 // JMP EAX end
Опкод 0417.
UPD. При загрузке сейва только вылет происходит, это то я и забыл проверить совсем
Last edited by Sergey81 (03-10-2010 19:54)
Offline
Offline
Ну дык чё, кто-нибудь знает как быстро загрузить игру?)))
Я думаю где-то рядом с 5D0DD0 _saveFileOpen нужная функция лежит.
Offline
Offline
По поводу провала предлагаю сделать как в Driver - Parallel Lines: после провала внизу экрана появляется надпись "Press Backspace to restart" и девятисекундный обратный отсчёт. Правда, там по нажатии бэкспейса миссия начиналась сразу же и с последнего чекпоинта, но это не столь важно...
Also known as HemiG
It's cool to Hate. It's cool to be a bloody guitarist.
Offline
По поводу провала предлагаю сделать как в Driver - Parallel Lines: после провала внизу экрана появляется надпись "Press Backspace to restart" и девятисекундный обратный отсчёт. Правда, там по нажатии бэкспейса миссия начиналась сразу же и с последнего чекпоинта, но это не столь важно...
Пока нету способа быстро загружать игру - это бессмысленно. Как альтернативу(читай - костыль) мне кажется можно делать так:
Активируем онлайн меню загрузки(как в моде с картой), но чтоб мышь не работала, там выделение будет на первом сейве, заставляем скрипт нажать за нас два раза клавишу "стрелка вверх", потом enter. Подтверждение загрузки убрать не проблема. Итого - будет загружен сейв без участия пользователя. Единственное, я знаю как сделать автонажатие кнопок A-Z, а вот возможно ли Up и enter, надо спросить у кого-нибудь другого.
Offline
Offline
тогда дай хотябы автонажатие тех что знаешь...
Так на этом форуме всё и написано, воспользуйся поиском.
Ну и здесь ещё можно почитать http://gtag.gtagaming.com/forums/index.php?showtopic=88
Last edited by Sergey81 (10-10-2010 19:27)
Offline
{$CLEO} var 20@ : Integer 21@ : Integer end 0652: 20@ = integer_stat 146 1@ = 0 0A9F: 0@ = current_thread_pointer 0A8E: 10@ = 0@ + 0x10 0A8D: 10@ = read_memory 10@ size 4 virtual_protect 0 0A8F: 11@ = 10@ - @lbl 0A8C: write_memory 0x004684BC size 4 value 11@ virtual_protect 1 0@ += 0x40 11@ += 2 0A8C: write_memory 11@ size 4 value 0@ virtual_protect 0 while true wait 0 if 1@ == 1 then while true wait 0 0652: 21@ = integer_stat 146 if and // $ONMISSION == 0 not Actor.Driving($PLAYER_ACTOR) 21@ == 20@ then Break else if and $ONMISSION == 0 not Actor.Driving($PLAYER_ACTOR) 0AB0: key_pressed 120 then 00A1: put_actor $PLAYER_ACTOR at 25@ 26@ 27@ 0AA5: call 0x619060 num_params 1 pop 0 6 end end end 00A0: store_actor $PLAYER_ACTOR position_to 25@ 26@ 27@ 1@ = 0 end end :lbl hex C705 00000000 01000000 // MOV DWORD PTR DS:[00000000], 1 B8 7B804600 // MOV EAX, 46807B FFE0 // JMP EAX end
C автосейвом перед миссией ничего не придумывается больше, так что сделал в этом примере так:
Начинаем миссию, записываем координаты игрока в маркере. Миссию проваливаем, нажимаем f9, переносимся на этот маркер, там делается сейв, и потом миссия начинается. Потом можно либо загружая сейв рестартовать, либо по f9.
Offline
Вопрос: какая часть вышеописанного кода ответственна за сам сейв, а какая - за детектирование фейла миссии? Если я правильно понял, то "0AA5: call 0x619060 num_params 1 pop 0 6" - это сэйв, а каую роль играет :lbl?
Also known as HemiG
It's cool to Hate. It's cool to be a bloody guitarist.
Offline
Offline