Модостроение. Редактирование и создание скриптов
|
|
denis2000 | Дата: Пн, 10.10.2011, 21:17 | Сообщение # 1 |
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
| Редактирование и создание скриптов Редактирование и создание скриптов на языке LUA Если у вас появились вопросы по применению скриптов в игре. Задавайте их в этой теме - умные головы, модосторители и просто разбирающиеся в программировании люди вам ответят.
Много интересного материала здесь (wiki), Lua_help.script, Help из SDK 0.7
Сборник модостроения ЗП v10.10.11 (автор: XOBAH): *.CHM, *.HTML [cut noguest=Если у вас не открывается файл CHM]Если у вас не открывается файл: 1. Запустите [Пуск]=>[Выполнить] (либо хот-кей [WIN]+[R]) 2. Введите команду (без кавычек) "regsvr32 %windir%\system32\hhctrl.ocx" 3. Если вылезло окно об успешном завершении вы все сделали правильно и можете перезагружать компьютер (а может и не надо) Также: файлы МОГУТ не открываться если в пути к файлу есть: символы кириллицы, "_", "#" Также: есть не стандартные программы-просмоторщики CHM файлов. Например: FBReader[/cut]
[cut=Где найти лог игры после вылета]Что такое LOG ошибки, и как мне его найти? Это система отладки происходивших вылетов, которая подается игрой в форме текста, хотя не всегда. Для того чтоб найти LOG необходимо зайти вот сюда:
В Win хр лог находится:
C:\Documents and Settings\All Users\Документы\S.T.A.L.K.E.R. - Зов Припяти\logs
Затем открываете первый файл в формате TXT, и в нем отбираете с низу 25 строчек. После кидаете эти 25 строчек в сообщение на форум.
В Win7 лог находится C:\Users\Public\Documents\S.T.A.L.K.E.R. - Зов Припяти\logs
Путь к папке с логом можно найти открыв файл fsgame.ltx который находится в корневой директории ЗП, за это отвечает строка: ... $app_data_root$ = true | false| $fs_root$| users\(тут мы указываем что папка пользователя, будет хранится рядом с Fsgame.ltx) ... $logs$ = true| false| $app_data_root$| logs\(а тут мы указываем что в папке пользователя, в подпапке Logs будут храниться наши логи) ... [/cut][cut=Получение более подробной информации о вылете (ХОВАН)] Открываем файл _g.script и ищем такую функцию: function abort(fmt, ...) Там есть заккомментированная строчка "--error_log(reason)", ее и надо расскомментировать, должно получиться вот так: Code function abort(fmt, ...) local reason = string.format(fmt, ...) error_log(reason) end Вот для примера два одинаковых вылета, первый с функцией по умолчанию, второй - с поправленной функцией
Первый: Code Expression : !m_error_code Function : raii_guard::~raii_guard File : D:\prog_repository\sources\trunk\xrServerEntities\script_storage.cpp Line : 748 Description : ....a.l.k.e.r. - Зов Припяти\gamedata\scripts\_g.script:478: bad argument #2 to 'format' (string expected, got nil) Второй: Code Expression : 0 Function : ErrorLog File : D:\prog_repository\sources\trunk\xrServerEntities\script_engine_script.cpp Line : 49 Description : 'Attempt to read a non-existant string field 'path_walk' in section 'walker@mechanic' [/cut]
Перед тем, как задать вопрос в этой теме, прочтите все предыдущие страницы, статьи в wiki по ссылке из шапки и соседнюю тему "Курс молодого бойца", возможно Ваш вопрос уже рассматривался.
Если произошел вылет - выкладываем лог! Вопрос ставим четко, не забываем указывать версию игры, установленные моды их версии, установленные фиксы модов и подробно ваши правки. Помните чем подробнее вопрос, тем точнее ответ.
"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник)
|
|
|
Эти 0 пользователя(ей) поблагодарили denis2000 за это полезное сообщение: |
|
|
denis2000 | Дата: Вт, 22.01.2013, 22:26 | Сообщение # 136 |
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
| yakuti, Из скрипта можно выполнить любую консольную команду кодом: Код get_console():execute("ТЕКСТ КОММАНДЫ"))
"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник)
|
|
|
Эти 0 пользователя(ей) поблагодарили denis2000 за это полезное сообщение: |
|
|
yakuti | Дата: Ср, 23.01.2013, 09:06 | Сообщение # 137 |
Отмычка
Пользователи
Сообщений: 46
| А какой текст команды, подскажите плиз
|
|
|
Эти 0 пользователя(ей) поблагодарили yakuti за это полезное сообщение: |
|
|
denis2000 | Дата: Ср, 23.01.2013, 22:49 | Сообщение # 138 |
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
| yakuti, demo_record x - начинается запись всего происходящего где x - это любая цифра или слово на английской раскладке!
"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник)
|
|
|
Эти 0 пользователя(ей) поблагодарили denis2000 за это полезное сообщение: |
|
|
Geonezis | Дата: Пт, 25.01.2013, 22:23 | Сообщение # 139 |
Разработчик «Смерти вопреки»
Свобода
Сообщений: 2360
| Здравствуйте. Наверное глупый вопрос. Где можно посмотреть список всех возможных параметров актора подобного типа: Код db.actor.health db.actor.power db.actor.radiation db.actor.bleeding Это те, которые вспомнил.
Смерти Вопреки Spectrum Project AP_Prodaction
|
|
|
Эти 0 пользователя(ей) поблагодарили Geonezis за это полезное сообщение: |
|
|
denis2000 | Дата: Пт, 25.01.2013, 23:39 | Сообщение # 140 |
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
| Geonezis, В файле lua_help.script, объект класса game_object обладает свойствами (property): Код property bleeding; property health; property morale; property power; property psy_health; property radiation;
"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник)
|
|
|
Эти 0 пользователя(ей) поблагодарили denis2000 за это полезное сообщение: |
|
|
Азазель | Дата: Вс, 27.01.2013, 17:59 | Сообщение # 141 |
Новичок
Пользователи
Сообщений: 77
| Доброго времени суток. Сейчас занимаюсь фиком для пака Fraser. И попутно вспомнил что в SGM версси что будет. Сделана g36 с двойным прицеливанием. Реально ли сделать так чтобы скажем на ПКМ прицеливание шло по колиматору. А при нажатии на СКМ идет по целику ?
Движок в курсе ваших желаний? denis2000
|
|
|
Эти 0 пользователя(ей) поблагодарили Азазель за это полезное сообщение: |
|
|
ted80 | Дата: Чт, 31.01.2013, 23:08 | Сообщение # 142 |
Гражданский
Пользователи
Сообщений: 15
| Здравствуйте denis2000, решил подправить скрипт выдачи сообщений о смерти НПС, что-бы было похоже на то, как описывается в книгах - с сообщениями об убийстве НПС - актором и др. НПС все прошло гладко.
[cut noguest=ПРИМЕР] if victim and IsStalker(victim) and IsStalker(who) then local dead_news = "Сообщение \\nПогиб сталкер !!! \\n%c[255,255,160,160]Имя: %c[default]"..victim:character_name().."\\n%c[255,160,255,160]Группировка: %c[default]\""..game.translate_string(victim:character_community()).."\"\\n%c[255,160,160,160]Локация: %c[default]"..game.translate_string(level.name()).."\\n%c[255,225,100,100]Убийца: %c[default]"..who:character_name().." \""..game.translate_string(who:character_community()).."\"" db.actor:give_game_news(dead_news, "ui\\ui_iconsTotal", Frect():set(498,188,83,47), 2000, 5000) end[/cut] [cut noguest=СКРИН][/cut]
Но вот с сообщениями о смерти от монстров и аномалий, проблема - как, при отсылке сообщений, получить названия монстров и аномалий, причастных к смерти НПС
[cut noguest] if victim and IsStalker(victim) and IsMonster(who) then local dead_news = "Сообщение \\nПогиб сталкер !!! \\n%c[255,255,160,160]Имя: %c[default]"..victim:character_name().."\\n%c[255,160,255,160]Группировка: %c[default]\""..game.translate_string(victim:character_community()).."\"\\n%c[255,160,160,160]Локация: %c[default]"..game.translate_string(level.name()).."\\n%c[255,225,160,160]Причина смерти:%c[default]".."" db.actor:give_game_news(dead_news, "ui\\ui_iconsTotal", Frect():set(498,188,83,47), 3, 4000) end
if victim and (IsStalker(victim) and (who == nil or (not IsStalker(who) and not IsMonster(who))) ) then local dead_news = "Сообщение \\nПогиб сталкер !!! \\n%c[255,255,160,160]Имя: %c[default]"..victim:character_name().."\\n%c[255,160,255,160]Группировка: %c[default]\""..game.translate_string(victim:character_community()).."\"\\n%c[255,160,160,160]Локация: %c[default]"..game.translate_string(level.name()).."\\n%c[255,225,160,160]Причина смерти: Аномалия".."" db.actor:give_game_news(dead_news, "ui\\ui_iconsTotal", Frect():set(498,188,83,47), 1, 4000) end[/cut]
Стабильный вылет: attempt to call method 'section_name' (a nil value)
Таки заработало : who:section() таким макаром [cut noguest=скрин][/cut]
теперь выглядит так: "..game.translate_string(who:section()).."
[cut noguest=Скрин][/cut]
Спасибо что подсказали где искать - теперь буду ковырять аномалии
Сообщение отредактировал ted80 - Пт, 01.02.2013, 17:42 |
|
|
Эти 0 пользователя(ей) поблагодарили ted80 за это полезное сообщение: |
|
|
denis2000 | Дата: Пт, 01.02.2013, 19:54 | Сообщение # 143 |
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
| ted80, Пробуй получать имя секции объекта who:section_name() и в зависимости от полученной строки составляй текст.
Цитата (ted80) who:section() таким макаром Ну или так, или можно еще по классам объектов clsid
"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник)
|
|
|
Эти 0 пользователя(ей) поблагодарили denis2000 за это полезное сообщение: |
|
|
Пpизpак | Дата: Пн, 25.02.2013, 19:10 | Сообщение # 144 |
Новичок
Пользователи
Сообщений: 64
| Здравствуйте. Может кто-нибудь объяснить что такое нет пакет? Сегодня лазил по файлам АМК-мода и нашел там вот такой код:
[cut noguest]--- Читает STATE и UPDATE нет-пакеты сталкера и разбирает их -- @param sobj Серверный объект сталкера -- @return Таблица параметров сталкера Код function read_stalker_params(sobj) g_stpk:w_begin(0) g_uppk:w_begin(0) sobj:STATE_Write(g_stpk) sobj:UPDATE_Write(g_uppk) g_stpk:r_seek(2) g_uppk:r_seek(2) local tbl=parse_se_stalker({}, g_stpk, g_uppk) return tbl end [/cut]
В ACDC видел что то подобное. Они(нет пакеты) как-то связаны со спавном?
Комп: Intel Core i5 2400 3.1GHz, 8gb RAM, GeForce GTX 570 1gb, Win 7 64bit Stalker 1.0004 + НС от 03.09.10 + DMX 1.3.5 + фикс 1.3.5 + свои правки Stalker 1.6.02 + SGM 1.7 + свои правки
Сообщение отредактировал Пpизpак - Пн, 25.02.2013, 19:11 |
|
|
Эти 0 пользователя(ей) поблагодарили Пpизpак за это полезное сообщение: |
|
|
denis2000 | Дата: Пн, 25.02.2013, 21:40 | Сообщение # 145 |
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
| Пpизpак, net_packet - это один из вспомогательных классов. Представляет собой буфер размером ровно 8 кбайт (т.е. 8192 байта). Из буфера можно последовательно читать и записывать данные, используя методы класса. Имеется текущая позиция чтения и записи. Теперь подробности. [cut=Информация из lua_help.script]class net_packet { net_packet ();
number w_tell(); number r_tell(); void w_begin(number); function r_begin(number&); function r_advance(number); function r_seek(number); number r_elapsed(); bool r_eof();
number r_u8(); void w_u8(number); number r_s8();
number r_u16(); void w_u16(number); number r_s16(); void w_s16(number); number r_u24(); void w_u24(number);
number r_u32(); void w_u32(number); number r_s32(); void w_s32(number);
number r_u64(); void w_u64(unsigned __int64); number r_s64(); void w_s64(__int64);
number r_float(); function w_float(number); string r_stringZ(); void w_stringZ(string); bool r_bool(); void w_bool(bool);
vector r_vec3(); void w_vec3(const vector&); matrix r_matrix(); void w_matrix(matrix&);
vector r_sdir(); void w_sdir(const vector&); vector r_dir(); void w_dir(const vector&);
number r_angle8(); void w_angle8(number); number r_angle16(); void w_angle16(number);
function r_float_q8(number&, number, number); function w_float_q8(number, number, number); function r_float_q16(number&, number, number); function w_float_q16(number, number, number);
function w_chunk_open8(number&); function w_chunk_open16(number&); function w_chunk_close16(number); function w_chunk_close8(number);
ClientID r_clientID(); void w_clientID(ClientID&); };[/cut] [cut=Более подробно о методах класса]net_packet() - конструктор, вызывается в виде глобальной функции так: local packet = net_packet() созданный пакет по умолчанию имеет позиции чтения и записи установленные в 0 Не всегда надо создавать свой пакет. Часто приходится иметь дело с уже готовым пакетом (см. следующую статью об использовании нетпакетов)
w_tell() - возвращает текущую позицию записи r_tell() - возвращает текущую позицию чтения r_advance(shift) - смещает позицию чтения на shift байт. Смещение может быть отрицательным. r_seek(pos) - устанавливает позицию чтения в pos r_elapsed() - возвращает w_tell() - r_tell() r_eof() - возвращает true, если r_tell() < w_tell(), иначе false
w_begin(number) - пишет двухбайтовое число в начало пакета и устанавливает позицию записи равной 2. Единственным другим способом начать запись с начала пакета - это создать новый пакет, у которого позиция записи установлена в 0. r_begin(number&) - Непонятный метод. По аналогии с w_begin должен читать с начала пакета два байта и устанавливать позицию чтения в 2. Однако у меня приводит к вылету. Ну, в любом случае можно обойтись и без него.
Важный момент! Нет никакого способа узнать, что в процессе чтения или записи позиция чтения или записи вышла за пределы пакета. При чтении подразумевается, что прочитать можно столько, сколько записано. Для этого и есть функции r_elapsed() и r_eof(). А вот при записи никакой границы сверху нет, поэтому можно запросто записать больше, чем 8 кбайт. Ясно, что при этом произойдёт переполнение буфера с почти обязательным последующим вылетом игры. Так что надо самостоятельно следить за размером позиции записи и проверять, чтобы при последующей записи она не вышла бы за размеры пакета. Для этого надо знать, сколько мы запишем, ещё до того, как запишем. В особенности это важно для строк, которые имеют переменную длину. Поступаем примерно так: Код if string.len(s) + 1 + packet:w_tell() > 8192 then -- здесь делаем что-то, например крашим игру и выводим сообщение, что не надо жадничать =) end packet:w_stringZ(s)Обратите внимание на "+ 1" в вычислении новой позиции записи. Строки имеют дополнительный невидимый нулевой символ в конце, и их физическая длина на один больше, чем длина в символах, которую возвращает функция string.len().
Остальные методы предназначены собственно для чтения и записи. Описывать их все в подробностях нет смысла, только общий принцип. Читаем так: local value = packet:r_XXX() здесь XXX - это тип значения, которое читается. Значение читается из буфера начиная с текущей позиции чтения, а позиция чтения увеличивается на размер читаемого значения. В переменную value будет помещено значение того типа, которое прочитано. аналогично пишем в буфер: packet:w_XXX(value) Значение пишется начиная с текущей позиции записи, а позиция записи увеличивается на размер типа XXX. для целых типов: u - знаковое значение s - беззнаковое значение 8, 16, 24, 32, 64 - один, два, три, четыре, восемь байт соответственно Обратите внимаение, что для типа s8 (знаковый байт) нет метода записи. Подозреваю, что вместо него можно использовать соответствующий метод для беззнакового типа. float - число с плавающей запятой одинарной точности, 4 байта stringZ - строка (размер равен длине + 1 байт) bool - логическое значение (1 байт) vec3 - объект типа vector - вектор из трёх float (12 байт) matrix - объект типа matrix. Состоит из 4-х векторов (48 байт) sdir - ? непонятно, на запись берёт вектор и пишет 6 байт dir - ? аналогично, но пишет 2 байта angle8 - ? берёт float и пишет 1 байт angle16 - ? аналогично, но пишет 2 байта четыре последних метода при чтении у меня вызывают вылет. зачем нужны, неизвестно. ClientID - объект класа ClientID. Судя по всему, это надо для сетевой игры. float_q8, float_q16 - пока непонятно Назначение методов с w_chunk_ вообще непонятно, тем более, что для них отсутствуют соответствующие методы на чтение.[/cut] [cut=Использование объектов класса net_packet]Собственно, законное использование нетпакетов - это буфер, в котором объект сохраняет своё состояние. Скорее всего это используется в первую очередь при передаче данных по сети. Потому и net_packet, т.е. буквально "сетевой пакет". Сначала объект записывает себя в пакет, затем он отправляется по сети. Похоже, однако, что используется не только при передаче по сети, но и для сохранения объектов вообще. Теперь конкретнее. 1. Сохранение состояния серверного класса На серверной стороне есть классы, унаследованные от cse_abstract. У них есть методы STATE_Read и STATE_Write. метод STATE_Read вызывается при загрузке состояния объекта из сохранёнки, в нём данные читаются из переданного методу пакета. STATE_Write вызывается при сохранении объекта, в нём данные объекта сохраняются в пакет. Если создать свой класс и перегрузить эти методы, то увидим такую картину: Код class "se_my_server_class" (<имя_базового_класса>)
function se_my_server_class:STATE_Write(packet) <имя_базового_класса>.STATE_Write(self, packet) -- базовый класс сохраняет свои данные -- здесь можно сохранить какие-то данные, в дополнение к данным базового класса packet:w_stringZ("моя строка") end
function se_my_server_class:STATE_Read(packet, size) <имя_базового_класса>.STATE_Read(self, packet) -- здесь базовый класс читает своё состояние из пакета -- здесь можно прочитать состояние своего класса, которое было сохранено ранее local s = packet:r_stringZ() -- получим строку "моя строка" end 2. Сохранение состояния клиентского класса На клиентской стороне также имеется нечто подобное. Это реализуется методами биндера save и load. При создании биндера (см. мою статью насчёт класса object_binder) можно в этих методах что-то сохранить. Однако, нетпакет используется для сохранения в методе save. в этом он подобен методу STATE_Write серверного класса. А вот при загрузке почему-то вместо нетпакета передаётся поток на чтение (класс reader). Таким образом трюкачество, описанное в следующем пункте для клиентских объектов не выйдет.
3. Перепаковка серверных объектов с целью изменения их параметров Предыдущие два варианта использования нетпакетов - это так сказать "законное" их использование. Но это не всё. Ничто не мешает вызывать методы STATE_Read и STATE_Write в произвольный момент времени, имитируя процесс сохранения и загрузки объекта. При этом можно сделать следующее: Код local packet = net_packet() -- создаём пустой пакет sobj:STATE_Write(packet) -- загрузили в наш пакет состояние серверного объекта -- используя методы класса net_packet меняем нужные нам значения. sobj:STATE_Read(packet, packet:w_tell()) -- записали в объект изменённое состояние обратно, имитируя процесс его загрузки Несколько замечаний: - Все эти манипуляции надо проводить над объектами в оффлайне, поскольку онлайновый объект регулярно обновляет серверную часть и полностью его переписывает, так что любые изменения такого рода будут потеряны. - Надо знать структуру нетпакета для того объекта, который Вы собираетесь изменить. При таких хирургических операциях запросто можно всё испортить.[/cut] По информации front
"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник)
|
|
|
Эти 0 пользователя(ей) поблагодарили denis2000 за это полезное сообщение: |
|
|
Пpизpак | Дата: Ср, 27.02.2013, 10:29 | Сообщение # 146 |
Новичок
Пользователи
Сообщений: 64
| denis2000, Спасибо. А STATE и UPDATE чем различаются? STATE для серверного, UPDATE для клиентского?
Добавлено (27.02.2013, 10:29) --------------------------------------------- denis2000, Цитата (denis2000) u - знаковое значение s - беззнаковое значение Цитата (denis2000) что для типа s8 (знаковый байт) Как это понимать? Насколько я знаю, здесь должно быть вот так: u(unsigned) - беззнаковое значение s(signed) - знаковое значение возможно Вы/автор ошиб(лись)ся при написании статьи.
P.S. Для информации: в С++ у типа int есть модификатор unsigned, который принимает только неотрицательные(беззнаковые) значения.
Комп: Intel Core i5 2400 3.1GHz, 8gb RAM, GeForce GTX 570 1gb, Win 7 64bit Stalker 1.0004 + НС от 03.09.10 + DMX 1.3.5 + фикс 1.3.5 + свои правки Stalker 1.6.02 + SGM 1.7 + свои правки
Сообщение отредактировал Пpизpак - Ср, 27.02.2013, 10:30 |
|
|
Эти 0 пользователя(ей) поблагодарили Пpизpак за это полезное сообщение: |
|
|
denis2000 | Дата: Ср, 27.02.2013, 13:54 | Сообщение # 147 |
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
| Цитата (Пpизpак) Как это понимать? Как написано в "Справочнике по функциям и классам" на сталкерине так и понимать. Все вопросы не ко мне, а в тему на АМК форуме.
"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..." (Чугунный всадник)
|
|
|
Эти 0 пользователя(ей) поблагодарили denis2000 за это полезное сообщение: |
|
|
KADAR | Дата: Вт, 05.03.2013, 17:35 | Сообщение # 148 |
Бывалый
Пользователи
Сообщений: 126
| Ребята, всем привет помощь нужна. решил адаптировать нано-броню из Monnoroch addons 1.5.2 для DMX мода 1.3.5. Делал-делал, за помощью обратился к одному человеку, ну и до делался до того что все вроде бы в норме, кроме одного в режиме брони костюм должен восстанавливать состояние костюма, но упорно этого не делает. Все скрипты перенес что связаны с костюмом из аддона Monnoroch addons 1.5.2 и еще добавлял скрипт bind_stalker из уже вырезанного варианта этой брони для ТЧ, при этом костюм работает, но не работают функции DMX мода. Следовательно я попытался (с помощью) адаптировать скрипт bind_stalker который содержится в DMX моде, функции DMX заработали, а режим брони перестал восстанавливать состояние костюма, что делать? Вот скрипт bind_stalker из уже вырезанного варианта этой брони для ТЧ который урезал возможности DMX. http://rghost.ru/44286613 А вот тот который адаптировался и после которого режим брони перестал восстанавливать состояние костюма http://rghost.ru/44286659
|
|
|
Эти 0 пользователя(ей) поблагодарили KADAR за это полезное сообщение: |
|
|
banananua | Дата: Ср, 06.03.2013, 09:39 | Сообщение # 149 |
Удаленные
| Всем привет , подскажите пожалуста почему при установке немецкой озвучки отряд альфа не разговаривает на немецком икак это можно реализовать ?
|
|
|
Эти 0 пользователя(ей) поблагодарили banananua за это полезное сообщение: |
|
|
KADAR | Дата: Ср, 06.03.2013, 15:56 | Сообщение # 150 |
Бывалый
Пользователи
Сообщений: 126
| banananua, нуу должны разговаривать НАЕМНИКИ если не ошибаюсь. Ты не совсем туда пишешь
|
|
|
Эти 0 пользователя(ей) поблагодарили KADAR за это полезное сообщение: |
|
|
|