[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
Форум » Игры серии GTA » GTA San Andreas » Вопросы по скриптингу Sanny Builder (Вы можете получить ответы на вопросы по SB)
Вопросы по скриптингу Sanny Builder
wmysterio
Администраторы
Скриптер
22.11.11 21:52
Offline
Если у вас возник вопрос по скриптингу Sanny Builder, обращайтесь! Мы постараемся решить вашу проблему wink Это ещё не значит, что все прям бросятся решать во чтобы то не стало, но ответ вы сможете вы получить как вариант решения или как невозможность или сложность решения.
УВАЖАЕМЫЕ ПОЛЬЗОВАТЕЛИ! ПРОСЬБА КОД СКРИПТОВ ПОМЕЩАТЬ В КОНСТРУКЦИЮ КОДА:

или

Также указывайте полный код скрипта, иначе причина ошибок может быть и не выявлена.
Прикрепления: 0248203.png(0.9 Kb) · 9085525.png(0.2 Kb)

SanKing
Друзья
01.06.14 13:46
Offline
Цитата Михан500 ()
И еще один вопрос, как сделать чтобы светофоры горели желтым светом всегда?
Это делается через адреса памяти. Я лично не знаю как.

Slivkin-Sergey
Модераторы
05.06.14 15:36
Offline
Блин, ну в упор ничего здесь не вижу... При старте игра просто виснет.
Код
:CURTASK_1
wait 0
if
Player.Defined($PLAYER_CHAR)
jf @CURTASK_1
0A8D: 0@ = read 0xBA67A4 1 0
if
0@ == 1
jf @CURTASK_1
0A8C: write 0x53BF8A 0x2 0x9090 1
0A8C: write 0x53BF96 0x6 0x90 1
0A8C: write 0x58FCC2 0x4 0x90909090 1
0A8C: write 0x58D4BE 0x8 0x90 1
while true
wait 0
03F0: enable_text_draw 1  
0343: set_text_draw_linewidth 300.0
03E4: enable_text_draw_align_right 1  
060D: draw_text_shadow 1 color_RGBA 0 0 0 255  
0340: set_text_draw_RGBA 0 255 0 255
045A: draw_text_1number 60.0 10.10 GXT 'DOLLAR' number 1  //$~1~
end

BoPoH
Друзья
05.06.14 17:13
Offline
Цитата Slivkin-Sergey ()
Блин, ну в упор ничего здесь не вижу... При старте игра просто виснет.
Ну, я не знаю, из-за чего у тебя там виснет... т.к. у меня ничего не виснет с этим скриптом. (я надеюсь, у тебя там в начале скрипта есть опкод 0000, если ты скинул весь код скрипта)
Вопрос в другом - в чём смысл проверки на открытость меню? До того, как ты поставишь нопы, скриптовый движок выполняться не будет.
Сперва нужно поставить нопы, а затем выполнять нужные тебе проверки, связанные с меню.
Отредактировал BoPoH - Четверг, 05.06.14, 17:14

Slivkin-Sergey
Модераторы
05.06.14 20:14
Offline
Цитата BoPoH ()
Вопрос в другом - в чём смысл проверки на открытость меню? До того, как ты поставишь нопы, скриптовый движок выполняться не будет.

В каком смысле "скриптовый движок выполняться не будет"? Вообще никакие скрипты? Или я что-то недопонял?..
Цитата BoPoH ()
(я надеюсь, у тебя там в начале скрипта есть опкод 0000, если ты скинул весь код скрипта)

У меня перед этим кодом только:
Код
:CURTASK
thread 'CURTASK'

Но thread - это ведь кейворд для опкода, так что с этим проблем быть не должно.

Добавлено (05.06.14, 17:33)
---------------------------------------------
Переставил нопы в начало скрипта, результат ещё хуже, теперь, как говорил СтепанГТ, "игра так зависла, что у меня комп форматировался на, ФИГ...". Если нопы после проверки - при нажатии на Win хоть Панель задач выскакивает, можно вырубить процесс, а сейчас пришлось перезагружаться, ибо даже Диспетчер не помог.

Добавлено (05.06.14, 17:43)
---------------------------------------------
Упс, извини, что наговорил тут, я просто ставил тематический тестовый скрипт от пака, а stdvars.txt у меня отродясь не было! Всё работает, но почему-то текст не выводится обыкновенным приоритетным опкодом.

Добавлено (05.06.14, 19:14)
---------------------------------------------
Вот ещё:

Код
if
Player.Defined($PLAYER_CHAR)
jf @CURTASK_1
wait 2500
0A8C: write 0x53BF8A size 2 value 0x9090 vp 1
0A8C: write 0x53BF96 size 6 value 0x90 vp 1
0A8C: write 0x58FCC2 size 4 value 0x90909090 vp 1
0A8C: write 0x58D4BE size 8 value 0x90 vp 1
repeat
wait 0
0A8D: 0@ = read 0xBA67A4 1 0
until 0@ == 1
01E5: show_text_1number_highpriority GXT 'DOLLAR' number 1 time 5000 flag 1
while true
wait 0
03F0: enable_text_draw 1  
03E4: enable_text_draw_align_right 0
060D: draw_text_shadow 1 color_RGBA 0 0 0 255  
0340: set_text_draw_RGBA 255 255 255 170
033E: set_draw_text_position 550.0 400.0 GXT 'TEST'
045A: draw_text_1number 550.0 420.0 GXT 'DOLLAR' number 1 // $~1~
end

Теперь текст выводится, но только когда зайду-выйду в меню 3-5 раз.
Отредактировал Slivkin-Sergey - Четверг, 05.06.14, 18:34

BoPoH
Друзья
06.06.14 15:18
Offline
Цитата Slivkin-Sergey ()
Теперь текст выводится, но только когда зайду-выйду в меню 3-5 раз.
У меня всё нормально выводится, дважды проверил.

Slivkin-Sergey
Модераторы
06.06.14 22:59
Offline
Хм-м, да уж, любит моя ГТАшка повыкидывать фокусы всякие. Буду разбираться...

А пока у меня есть вопрос по коду твоей скм-функции, который ты оставлял несколько постов выше.
Цитата BoPoH ()
:EnableActorsCollision // 0AB1: @EnableActorsCollision 0

Не мог бы ты прокомментировать её строки? В частности, мне непонятны назначения некоторых команд, как, например, 12@ -= 1.

BoPoH
Друзья
07.06.14 00:01
Offline
Цитата Slivkin-Sergey ()
Не мог бы ты прокомментировать её строки? В частности, мне непонятны назначения некоторых команд, как, например, 12@ -= 1.
Изначально в эту переменную я считываю максимальное кол-во педов в пуле. Но, т.к. я использую это значение в условии цикла

Код
for 4@ = 0 to 12@
 то нужно знать об одной важной вещи. В SB цикл for распознаётся таким образом, что цикл продолжает выполняться пока переменная 4@ не станет больше 12@. Если они равны, цикл также выполняется. Учитывая то, что отсчёт мы ведём с нуля, а не с единицы, то последним "ID" педа, который мы проверяем будет равен максимальному кол-ву педов минус один. Если у нас было максимальное кол-во педов 140, то последний ID педа будет 139. Для этого я и отнимаю от максимального кол-ва педов единицу.

Slivkin-Sergey
Модераторы
07.06.14 19:41
Offline
А что насчёт строк
Цитата BoPoH ()
0A8D: 11@ = read_memory 10@ size 4 virtual_protect 0 // CPed Array

Цитата BoPoH ()
10@ += 8

Цитата BoPoH ()
0085: 5@ = 4@
5@ *= 0x7C4
5@ += 0x18
005A: 5@ += 11@
0A8D: 6@ = read_memory 5@ size 4 virtual_protect 0 // RwObject
if
6@ > 0
then
5@ -= 0x18

?

BoPoH
Друзья
07.06.14 23:32
Offline
Я думаю, так будет проще:

Код
:EnableActorsCollision // 0AB1: @EnableActorsCollision 0  
actor.StorePos($PLAYER_ACTOR, 0@, 1@, 2@) // Записываем позицию игрока в 0@, 1@, 2@
0A8D: 10@ = read_memory 0xB74490 size 4 virtual_protect 0 // Читаем в 10@ указатель на пул педов
0A8D: 11@ = read_memory 10@ size 4 virtual_protect 0 // Читаем в 11@ указатель на массив педов
10@ += 8 // Смещение по которому в структуре пула записано максимальное кол-во педов
0A8D: 12@ = read_memory 10@ size 4 virtual_protect 0 // Читаем в 12@ максимальное кол-во педов в пуле
12@ -= 1 // Отнимаем от максимального кол-ва педов единицу
// Нужно для того, чтобы не перейти границу массива

for 4@ = 0 to 12@ // В цикле перебираем всех педов в пуле
       0085: 5@ = 4@  // Записываем в 5@ текущий ID (номер итерации в цикле); делаем это для того, чтобы потом не изменять переменную 4@
       5@ *= 0x7C4 // Умножаем ID на размер структуры педа
       005A: 5@ += 11@ // Теперь складываем указатель на массив педов и смещение, по которому будет находиться пед с указанным ID
      // Сейчас у нас в 5@ находится указатель на педа с ID равному текущей итерации в цикле
       5@ += 0x18 // Прибавляем смещение, по котому записан RwObject педа
       0A8D: 6@ = read_memory 5@ size 4 virtual_protect 0 // Читаем его в переменную 6@
       if  
       6@ > 0 // Если указатель больше нуля, значит пед с таким ID действительно существует
       then  
           5@ -= 0x18 // Отнимаем смещение RwObject, которое мы прибавили ранее, так мы снова получим указатель на педа
           0AEA: 7@ = actor_struct 5@ handle // Получаем скриптовый хендл педа  
           if and  
           87D6: not 7@ == $PLAYER_ACTOR // ставим необходимые проверки  
           80DF: not actor 7@ driving  
           then  
               0619: enable_actor 7@ collision_detection 1 // производим необходимое действие с педом  
           end  
       end  
end  
0AB2: ret 0

В принципе, проверку на существование педа, можно было реализовать по-другому:

Код
005A: 5@ += 11@ // Теперь складываем указатель на массив педов и смещение, по которому будет находиться пед с указанным ID
      // Сейчас у нас в 5@ находится указатель на педа с ID равному текущей итерации в цикле
       0AEA: 7@ = actor_struct 5@ handle // Получаем скриптовый хендл педа
       if  
       actor.Defined(7@) // Проверяем существование педа
       then
           if and  
           87D6: not 7@ == $PLAYER_ACTOR // ставим необходимые проверки  
           80DF: not actor 7@ driving  
           then  
               0619: enable_actor 7@ collision_detection 1 // производим необходимое действие с педом  
           end  
       end

Михан500
Пользователи
10.06.14 20:37
Offline
Необходимо защитить main.scm от декомпилирования, как в dyom v8.1.

BoPoH
Друзья
11.06.14 04:36
Offline
Цитата Михан500 ()
Необходимо защитить main.scm от декомпилирования, как в dyom v8.1.
А то там особо важная информация biggrin
Ребят, любую "защиту" можно сломать. При чём очень просто.
Ну, я не знаю, какая там в диоме "защита" стоит, но можно попробовать подменить хекс-редактором какой-нибудь опкод в майне на несуществующий. Хотя такое легко декомпилируется при включенной опции IGNORE_UNKNOWN...
Лично я когда-то практиковал удаление одного байта в хекс-коде опкода 0000. SB просто зависал при декомпиляции.

Slivkin-Sergey
Модераторы
11.06.14 21:25
Offline
Теперь точно ничего не понимаю, не могу загрузить банальнейшую текстуру, зависон неизбежен:
Код
:TEXTURE
thread 'TEXTURE'
wait 0      
if
0AB0:  key_pressed 49
jf @TEXTURE
0390: load_txd_dictionary 'LD_DUAL'
038F: load_texture "light" as 1
wait 250

:TEXTURE_1
wait 0
if
0AB0:  key_pressed 49
then
0391: release_txd_dictionary
wait 250
jump @TEXTURE
end           
jump @TEXTURE_1

BoPoH
Друзья
12.06.14 13:11
Offline
Цитата Slivkin-Sergey ()
Теперь точно ничего не понимаю, не могу загрузить банальнейшую текстуру, зависон неизбежен:
Я даже не знаю, что тут может быть не так, т.к. у меня ничего не зависает.
Отредактировал BoPoH - Четверг, 12.06.14, 13:12

Михан500
Пользователи
12.06.14 15:51
Offline
BoPoH, какая важная информация говоришь?Я не хочу чтобы кто то открыл мой main.scm, взял какую то любую часть кода и вставил под своим именем.Хочу защититься от плагиата, я немало в этом main.scm кода написал...Я знаю что любую защиту можно обойти, но ведь не каждый человек сможет.Попробую hex editor' ом удалить один байт 0000: . Спасибо на этом.

Добавлено (12.06.14, 14:46)
---------------------------------------------
Все, немного практики в hex editor, и при декомплияции выдает Range check error, а в игре все работает.

Добавлено (12.06.14, 14:51)
---------------------------------------------
А если убрать защиту hex editor' ом, то sanny builder выдает неверный заголовок файла.

Отредактировал Михан500 - Четверг, 12.06.14, 15:28

Slivkin-Sergey
Модераторы
12.06.14 18:38
Offline
Цитата Михан500 ()
А если убрать защиту hex editor' ом, то sanny builder выдает неверный заголовок файла.

Можешь скинуть сюда, если окончательно уверен в надёжности этой защиты, такое открывается на раз-два, причём стандартными средствами СБ.
Добавлено (12.06.14, 17:25)
---------------------------------------------
Да и вообще, чего там может быть такого, чтоб так яростно это защищать? Не было ещё ни одного случая кражи глобальных модов. Я тоже уже почти год пишу проект на main.scm, там фишки и похлеще есть, например, тряпично-кукольная физика падений, но я же не паранойю и не пекусь о своём чувстве собственного достоинства, что якобы кто-то это сделал, а я нет. В случае кражи я просто покажу неверящим кусок исходного кода - самая надёжная защита.

Добавлено (12.06.14, 17:38)
---------------------------------------------
Цитата BoPoH ()
// Читаем в 10@ указатель на пул педов
// Читаем в 11@ указатель на массив педов

ВОТ те самые два слова! Чем же они так отличаются?
Цитата BoPoH ()
в структуре пула

Пул - это ведь что-то наподобие массива с элементами, а структура - сборище данных в одной переменной?.. Хотя я определённо чего-то недопонимаю, но чего?..
Цитата BoPoH ()
// Прибавляем смещение, по котому записан RwObject педа

Что это за зверь такой - RwObject? Не от него ли наследуется CPed, или всё-таки от CPlaceable?
Ну а в целом, эта субъективно-мутная каша с перебором педов в массиве начинает проясняться для меня...
Отредактировал Slivkin-Sergey - Четверг, 12.06.14, 18:39

BoPoH
Друзья
12.06.14 21:23
Offline
Ну, тебе нужно для начала понять, что собой представляет структура. Потому что пул (Pool) - это структура. Структура - это набор переменных, в некотором роде. Указатель - это адрес чего-либо (структуры, массива, переменной) в памяти. Указатель представляет собой обычное число (4 байта).
Следует понимать, что любые данные находятся где-то в памяти. Если мы говорим о работе с ними через CLEO, то можно подразумевать, что мы всегда будем работать с указателями. Т.е. мы будем иметь не структуру, а указатель на структуру. Это как если бы мы, вместо того, чтобы хранить число в переменной 1@, записали бы в 1@ указатель на участок памяти и потом читали бы эту память или записывали в неё, имея её адрес (указатель) в переменной 1@. В таком случае, можно (грубо говоря) назвать переменную 1@ указателем.
Вернёмся к структурам. К примеру, возьмём структуру пула педов.
Код
struct CPedPool
{
      CPed *objects;
      char *flags;
      int size;
      int top;
      char initialized;
      char field_11;
};


Так она будет выглядеть на языке C++ (в оригинале она выглядит немного по-другому, имена элементов должны быть другими, эта структура - лишь результат реверс-инжиниринга). Нас интересует здесь самый первый указатель - это указатель на массив педов. Этот массив представляет собой просто "кусок" памяти, размер которого составляет размер структуры педа помноженный на макс. кол-во педов в массиве. Все структуры педов идут друг за другом, если можно так выразиться. Так вот, оффсет первого параметра в структуре составляет 0, т.к. он первый, следовательно, к указателю на структуру пула нам ничего не нужно прибавлять (вообразим, что мы прибавили ноль), просто читаем значение по этому адресу. Таким образом мы получаем указатель на массив педов.
А чтобы, к примеру, получить размер массива, нам нужно прочитать параметр size в структуре пула. Учитывая, что первые два параметра являются указателями (т.е. каждый занимает в структуре по 4 байта), то нужно прибавить 8 к указателю на структуру пула и прочесть значение.
Забыл кое-что упомянуть - о том, как мы получили указатель на структуру пула. Он хранится в памяти игры, по "постоянному" адресу (0xB74490). Прочтя его, мы получаем указатель на пул. А уже в структуре пула хранится указатель на массив педов. Поэтому нам пришлось сначала получить указатель на пул, чтобы добраться до педов.

Что касается RwObject. Это такая структура, которая включает в себя много разных других структур (о которых нет смысла сейчас говорить), проще говоря, все они представляют модель (вертексы, полигоны, текстуры). Кстати, префикс Rw в начале названия структуры - отсылка к движку RenderWare, на котором основана игра. По сути, RwObject - это структура из движка RenderWare.
Что касается наследия. Если говорить о полной цепочке, то CPed наследуется от CPhysical, а тот - от CEntity, который в свою очередь наследуется от CPlaceable. RwObject не является наследником или наследуемым, это просто параметр в структуре CEntity (по смещению 0x18). А учитывая то, что CPed берёт наследие от CEntity в определённом смысле, то в его структуре так же будет находиться указатель на RwObject по смещению 0x18.
Проще всего наследие представить в виде матрёшек, когда маленькие спрятаны внутри больших. Тогда, то, что находится в маленькой матрёшке, по сути, находится и в большой.

Добавлено (12.06.14, 20:23)
---------------------------------------------

Цитата Slivkin-Sergey ()
Да и вообще, чего там может быть такого, чтоб так яростно это защищать? Не было ещё ни одного случая кражи глобальных модов.
Я к тому же веду. Может быть, любой дурак может открыть main.scm и скопировать код. Но далеко не каждый сможет его правильно применить. Я почти уверен, что никаких особо сложных и ценных алгоритмов у тебя там нет.
Я вот недавно выложил исходники одного из своих модов. И знаешь, они никому, по ходу, не пригодились, поскольку никто не понял что к чему там happy . По крайней мере, я не видел ни одного мода на основе моих исходников.
Конечно, я тоже беспокоился раньше о том, что "мой код могут стырить", но... просто это никому нафиг не нужно. На свете есть гораздо более стоящие вещи.
Отредактировал BoPoH - Четверг, 12.06.14, 21:14

Slivkin-Sergey
Модераторы
13.06.14 16:56
Offline
Погоди-ка... Я правильно понял, что CPedPool - это, грубо говоря, склад данных о массиве CPed?
Цитата BoPoH ()
Указатель - это адрес чего-либо (структуры, массива, переменной) в памяти. Указатель представляет собой обычное число (4 байта).

О принципе размещения данных в памяти я знаю, всё-таки в С++ я тоже практикуюсь.
Цитата BoPoH ()
Rw в начале названия структуры - отсылка к движку RenderWare, на котором основана игра

Эм-м...
Цитата BoPoH ()
Прочтя его, мы получаем указатель на пул.

То есть пролог об указателях был для этого; тип [pointer] в памяти можно просто считать и манипулировать как с обычным хэндлом?

И небольшой вопрос по С++, ибо он настолько мал, что не хочется набивать тему; если я напишу (грубо говоря,, синтаксис указателей я точно сейчас не помню):
Код
int a;
int b = &a;
&a = 0x11111

То будет ли это значить, что я помещу переменную в ячейку по адресу 0x11111?

BoPoH
Друзья
13.06.14 22:24
Offline
Цитата Slivkin-Sergey ()
int a; int b = &a;
&a = 0x11111
Так делать нельзя. В C++ есть различия между указателем на переменную определённого типа данных и самой переменной. Т.е. если ты объявил интовую переменную a, то &a нельзя записать в переменную того же типа int. Или нельзя присвоить интовой переменной адрес другой интовой переменной (как у тебя написано).
В C++ существуют переменные-указатели. По сути, это обычная 4-байтовая переменная, но, скажем, указатель на интовую переменную не тоже самое, что указатель на флоатовую переменную.
Вероятно, ты хотел написать что-то вроде этого:

Код
int a;
int *b = &a; // Переменная b в данном случае будет являться указателем на переменную a
*b = 0x11111;

Цитата Slivkin-Sergey ()
То есть пролог об указателях был для этого; тип [pointer]в памяти можно просто считать и манипулировать как с обычным хэндлом?
Пролог был для этого, да. Хендл и указатель - это разные вещи. Да, и мне не очень понятно, как можно манипулировать с обычным хендлом? Что ты подразумеваешь?
Представь, что игра - это не экзешник, а код на C++ (потому что изначально так и было). И вот где-то там было примерно такое объявление:

Код
CPedPool *PedPool;
Т.е. PedPool - это переменная-указатель на пул педов. После инициализации пула (при старте игры) ей присвоили адрес самого пула (для пула выделили память, а её адрес записали в переменную-указатель).
Так вот, в екзешнике эта самая переменная-указатель находится по определённому адресу (который мы знаем). Этот адрес мы и читаем как-бы из той самой переменной-указателя.

Цитата Slivkin-Sergey ()
Я правильно понял, что CPedPool - это, грубо говоря, склад данных о массиве CPed?
Довольно грубо, но в общем смысле верно. Лучше почитать про структуры и классы в C++;

Slivkin-Sergey
Модераторы
14.06.14 08:03
Offline
Цитата BoPoH ()
Вероятно, ты хотел написать что-то вроде этого:

Да-да, забыл звёздочку поставить.
Цитата BoPoH ()
Лучше почитать про структуры и классы в C++;

Я прочитал, но так и не понял толком, чем они отличаются :dummy:
Цитата BoPoH ()
Хендл и указатель - это разные вещи

Я знаю. Но ты ведь говорил, что переменную в СБ можно представить как указатель, то есть, манипулируя с хэндлом в СБ, манипулируем с указателем на объект на машинном уровне.
Манипулировать - это значит использовать его. Например, Actor.SetImmunities().

BoPoH
Друзья
14.06.14 16:36
Offline
Цитата Slivkin-Sergey ()
Но ты ведь говорил, что переменную в СБ можно представить как указатель
В принципе да. Просто хендл - это, обычно, некий идентификационный номер. А указатель - это адрес в памяти.

Цитата Slivkin-Sergey ()
Я прочитал, но так и не понял толком, чем они отличаются
В принципе, ничем особенным. Просто классы можно наследовать от других классов, у классов есть свои функции, применимые только к объектам данного класса или ко всем классам, наследуемым от этого класса (у структур нет такого). У классов много особенностей, короче. Хотя, данные хранятся точно так же, как в структурах.
Можно сказать, что класс - это та же самая структура, но на неё ещё повесили возможность наследования и добавили функции, применимые к этому классу.

Форум » Игры серии GTA » GTA San Andreas » Вопросы по скриптингу Sanny Builder (Вы можете получить ответы на вопросы по SB)
Поиск: