You are not logged in.
В CLEO скриптах в настоящее время нельзя использовать опкоды set_status_text и set_timer, а также сопутствующие им опкоды. Связано это с тем, что эти опкоды требуют задания глобальной переменной, которые, за редким исключением, использовать в CLEO-скриптах нельзя.
Поскольку написать альтернативу этим опкодам довольно непросто, я решил пойти другим путем. Я написал 4 функции, которые работают аналогично опкодам 03C3, 03С4, 014F, 0151, только принимают в качестве переменной - локальную переменную. Это позволяет использовать статус_текст и таймеры в CLEO-скриптах и CLEO-миссиях.
Внимание! Для корректной работы функций нужен CLEO 3 v3.0.950 и выше
Функции работают только в GTA: SA v1.0
:AddStatusText 0AB1: call_scm_func @__VarToOffset 1 0@ 0@ 0AB1: call_scm_func @__LabelToOffset 1 2@ 2@ 0AA6: call_method 0x0044CDA0 struct 0x00BA1788 num_params 4 pop 0 ( LINE = 3@ GXT = 2@ TYPE = 1@ VARNUMBER = 0@ ) 0AB2: ret 0 :RemoveStatusText 0AB1: call_scm_func @__VarToOffset 1 0@ 0@ 0AA6: call_method 0x0044CE80 struct 0x00BA1788 num_params 1 pop 0 ( VARNUMBER = 0@ ) 0AB2: ret 0 :SetTimer 0AB1: call_scm_func @__VarToOffset 1 0@ 0@ 0AB1: call_scm_func @__LabelToOffset 1 2@ 2@ 0AA6: call_method 0x0044CD50 struct 0x00BA1788 num_params 3 pop 0 ( TYPE = 1@ GXT = 2@ VARNUMBER = 0@ ) 0AB2: ret 0 :StopTimer 0AB1: call_scm_func @__VarToOffset 1 0@ 0@ 0AA6: call_method 0x0044CE60 struct 0x00BA1788 num_params 1 pop 0 ( VARNUMBER = 0@ ) 0AB2: ret 0 :__VarToOffset 0A9F: 1@ = current_thread_pointer 0A8E: 2@ = 1@ + 0xDC // mission Flag 0A8D: 2@ = read_memory 2@ size 1 virtual_protect 0 if 2@ == 1 then 1@ = 0x00A48960 // mission locals else 1@ += 0x3C end 0@ *= 4 005A: 1@ += 0@ // address of the local variable 1@ -= 0xA49960 0AB2: ret 1 1@ :__LabelToOffset if 0@ == 0 then 0AB2: ret 1 0 end 0A9F: 1@ = current_thread_pointer 1@ += 0x10 0A8D: 1@ = read_memory 1@ size 4 virtual_protect 0 // baseIP 0062: 1@ -= 0@ // label address 1@ += 3 0AB2: ret 1 1@ :StatusText 0900: 'BB_19' 0000:
Вот эти 4 функции.
1. AddStatusText эмулирует опкод 03C4: set_status_text $BEEFYBARON_SCORE type 0 GXT 'ZER2_43'.
Пример использования:
0AB1: call_scm_func @AddStatusText 4 VARNUMBER = 33 TYPE = 0 GXT = @StatusText LINE = 3
Параметры:
VARNUMBER = 33 - это номер локальной переменной, значение которой будет выведено (т.е. 33@)
TYPE = 0 - как и в 03С4 тип статуса: полоска (1) или число (0).
GXT = @StatusText - это основное отличие от опкода. Напрямую передать строку в функцию нельзя (также как и в новый поток, например). Поэтому мы передаем метку, на которой стоит опкод 0900 с нужным текстом (GXT) (в данном случае 0900: 'BB_19'). Можно добавить несколько подряд опкодов 0900, каждый со своим GXT и своей меткой, и передавать в функцию нужную метку. Надеюсь, с этим проблем не возникнет.
Можно вместо метки написать 0, тогда будет выводиться только число, без текста слева.
LINE = 3 - номер строки, на которой появится статус. Если равно 0, то статус добавится к первой свободной строке.
2. RemoveStatusText эмулирует опкод 0151: remove_status_text $1924
Пример использования:
0AB1: call_scm_func @RemoveStatusText 1 VARNUMBER = 33
Параметр только один - номер локальной переменной, которая использовалась в AddStatusText.
3. SetTimer эмулирует опкод 03C3: set_timer_to $1923 type 1 GXT 'BB_19'
Пример использования:
0AB1: call_scm_func @SetTimer 3 VARNUMBER = 1 TYPE = 1 GXT = @StatusText
Параметры VARNUMBER и GXT аналогичны AddStatusText. Параметр TYPE означает вид таймера: увеличивающийся или уменьшающийся.
4. StopTimer эмулирует 014F: stop_timer $1923
Пример использования:
0AB1: call_scm_func @StopTimer 1 VARNUMBER = 1
Параметр - номер локальной переменной, которая использовалась в SetTimer.
Поскольку это лишь эмуляция настоящих опкодов, все ограничения сохраняются (1 таймер и 4 статуса).
Чтобы использовать эти функции, нужно скопировать их без изменений в ваш скрипт, изменить или добавить нужные GXT-ключи, и вызывать соответствующую функцию.
Вот пример скрипта, который в течение 10 секунд показывает состояние переменной 33@ (т.е. таймера)
http://cleo.sannybuilder.com/scripts/status_text.cs
Offline
Круто! То, что доктор прописал. Спасибо огромное:^
Offline
Простите, но я что-то не очень понял. Дайте плиз пример скрипта, где при нажатии [0ab0: 17] включается таймер с обратным отчетом в 8 секунд.
Offline
Небольшое дополнение: с появлением новых опкодов в CLEO 4 код из первого сообщения можно упростить Вместо вызова дополнительных функций __VarToOffset и __LabelToOffset можно использовать опкоды 0AC6 и 0AC7. Так код станет еще компактнее
Но если с 0AC6 (labelToOffset) вроде все понятно, то как лучше приткнуть сюда 0AC7 (varToOffset), я пока не соображу. Кто подскажет?))
Offline
Но если с 0AC6 (labelToOffset) вроде все понятно, то как лучше приткнуть сюда 0AC7 (varToOffset), я пока не соображу. Кто подскажет?))
Как то так...
:__VarToOffset 0AC6: 1@ = label @0AC7 offset 1@ += 3 0A8C: write_memory 1@ size 2 value 0@ virtual_protect 0 :0AC7 0AC7: 0@ = var 0@ offset 0@ -= 0xA49960 0AB2: ret 1 0@
Offline
Остроумное решение) Интересно, еще варианты будут?
edit:
Хорошо, мой вариант.
Нам нужно получить адрес локальной переменной, и тут возможны два случая. Либо это одна из переменных потока, либо миссионная переменная. Надеюсь, 0AC7 различает эти варианты (?) и возвращает правильный адрес. Поскольку остальные переменные будут расположены в этой же области памяти, можно просто добавить смещение до искомой переменной к адресу 0@ (начало области лок. переменных).
:__VarToOffset 0A90: 1@ = 0@ * 4 // смещение до переменной 0AC7: 0@ = var 0@ offset // начало блока локальных переменных 005A: 0@ += 1@ // (int) // получаем адрес нужной переменной 0@ -= 0xA49960 0AB2: ret 1 0@
Last edited by Seemann (27-05-2010 01:04)
Offline
Можно воспользоваться массивами
:__VarToOffset 0AC7: 0@ = var 0@(0@,1i) offset 0@ -= 0xA49960 0AB2: ret 1 0@
Offline