#1 13-06-2008 12:02

Seemann
Registered: 07-08-2006
Posts: 2,089

[CLEO3] Как использовать опкоды set_status_text и set_timer

В 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

#2 13-06-2008 13:42

flashTrash
From: Н.Новгород
Registered: 21-02-2007
Posts: 260
Website

Re: [CLEO3] Как использовать опкоды set_status_text и set_timer

Круто! То, что доктор прописал. Спасибо огромное:^

Offline

#3 04-03-2010 03:12

GTASA
Registered: 13-09-2008
Posts: 476

Re: [CLEO3] Как использовать опкоды set_status_text и set_timer

Простите, но я что-то не очень понял. Дайте плиз пример скрипта, где при нажатии [0ab0: 17] включается таймер с обратным отчетом в 8 секунд.

Offline

#4 25-05-2010 03:29

Seemann
Registered: 07-08-2006
Posts: 2,089

Re: [CLEO3] Как использовать опкоды set_status_text и set_timer

Небольшое дополнение: с появлением новых опкодов в CLEO 4 код из первого сообщения можно упростить smile Вместо вызова дополнительных функций __VarToOffset и __LabelToOffset можно использовать опкоды 0AC6 и 0AC7. Так код станет еще компактнее wink

Но если с 0AC6 (labelToOffset) вроде все понятно, то как лучше приткнуть сюда 0AC7 (varToOffset), я пока не соображу. Кто подскажет?))

Offline

#5 25-05-2010 14:00

Sanchez
Registered: 18-08-2006
Posts: 280

Re: [CLEO3] Как использовать опкоды set_status_text и set_timer

Seemann wrote:

Но если с 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

#6 25-05-2010 18:59

Seemann
Registered: 07-08-2006
Posts: 2,089

Re: [CLEO3] Как использовать опкоды set_status_text и set_timer

Остроумное решение) Интересно, еще варианты будут?

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

#7 28-05-2010 16:36

Alien
Registered: 12-10-2008
Posts: 564

Re: [CLEO3] Как использовать опкоды set_status_text и set_timer

Можно воспользоваться массивами

:__VarToOffset
0AC7: 0@ = var 0@(0@,1i) offset
0@ -= 0xA49960
0AB2: ret 1 0@

Offline

Board footer

Powered by FluxBB