Перейти к контенту
n6260

Народная 2010 разработка

Рекомендуемые сообщения

"Что у нее внутри, и как это сделать лучше". Для тех, кто уже разбирается в скриптах, конфигах, текстурах и "других страшных словах" ©, и имеет желание и время действительно делать их лучше.
См. подробности в первом посте.

Тема НЕ является ни столом заказов, ни службой техподдержки, ни справочным бюро.

Изменено пользователем Dennis_Chikin
  • Нравится 2
  • Полезно 1
Ссылка на комментарий
Таблицы в луа - это ассоциативный массив. Хранятся пары - ключ, значение. Но их можно использовать как массивы, списки, стек и прочее(см. список структур данных).
Здесь таблицы раскрыты немного не так.
The implementation of tables in Lua involves some clever algorithms. Every table in Lua has two parts: the array part and the hash part. The array part stores entries with integer keys in the range 1 to n, for some particular n. All other entries (including integer keys outside that range) go to the hash part.

Таблицы в луа - это ассоциативный массив. Хранятся пары - ключ, значение. Но их можно использовать как массивы, списки, стек и прочее(см. список структур данных).

 

Оператор # возвращает не длину таблицы :) Он возвращает номер элемента после которого идет nil. То есть в частном случае когда в таблице нилов нет, вернется длина таблицы. В общем, как только начали баловаться присвоением нилов, вернет длину до первого нила

Не совсем так.

Вот такой код

    local t1 = {1,2,3,4,5}
    t1[2] = nil
    get_console():execute("load ~~~ testTables table.getn(t1): "..tostring(table.getn(t1)))
    get_console():execute("load ~~~ testTables #t1: "..tostring(#t1))
    amk.dump_table(t1)

даёт такой лог

! Cannot find saved game ~~~ testtables table.getn(t1): 5
! Cannot find saved game ~~~ testtables #t1: 5
! Cannot find saved game ~~~ .1 => 1
! Cannot find saved game ~~~ .3 => 3
! Cannot find saved game ~~~ .4 => 4
! Cannot find saved game ~~~ .5 => 5

Дамп таблицы в конце лога построен на for k,v in pairs t do, поэтому элемент под номером 2 пропущен. Но самое интересное, что утряски таблицы не произошло и оба способа получения длины не сработали.

 

P.S. Это я лишнего из лога взял...

Изменено пользователем sapsan
Ссылка на комментарий

Kolmogor

sapsan

 

Так, ну вообще это больше всего похоже на отличия между разными версиями самого Lua. А какая именно версия строена в игру? И не изменяли ли её самостоятельно разработчики?

Отладчик и скриптер мода OGSE. Автор схемы "Компаньоны", стреляющего БТРа и многих других полезностей :wink:

Ссылка на комментарий

sapsan,

Странный лог :) Почему t, а не t1

! Cannot find saved game ~~~ testtables table.getn(t): 1

! Cannot find saved game ~~~ testtables #t: 2

! Cannot find saved game ~~~ testtables t.n: 1

Лог поправил. Там лишнее было. sapsan

 

устарелоСейчас сам поэкспериментировал: никакого внутреннего n нет по-видимому - table.getn всегда пробегается по таблице и возвращает наибольшее значение ключа(если занилить последний элемент, то вернет на единицу меньшее значение). #t у меня всегда равна table.getn(t) Если не используешь вставку t[#t+1] = 1 sapsan

 

Еще поэкспериментировал :) Последние данные такие:

- table.insert и table.remove заводят внутреннюю переменную, в которой хранят длину таблицы(ее имя то ли не n, то ли она не доступна из скрипта). table.getn, если эта переменная есть, выдает ее значение, если нет, перебирает таблицу и возращает максимальный ключ.

- # насколько я понял всегда перебирает таблицу и возвращает максимальное значение ключа

 

Утряски и не должно было быть. Утряска будет, если пользоваться table.remove

 

kamikazze,

проверил на ТЧ 4 и 6 патчи, ЗП ведет себя одинаково, как в этом посте выше написал

Изменено пользователем Kolmogor
Ссылка на комментарий

Ещё из экспериментов с таблицами.

    local t2 = {2, 3}
    t2[#t2+1] = 4
    t2[#t2+1] = 5
    get_console():execute("load ~~~ testTables table.getn(t2): "..tostring(table.getn(t2)))
    get_console():execute("load ~~~ testTables #t2: "..tostring(#t2))
    table.remove(t2, 2)
    table.remove(t2)
    get_console():execute("load ~~~ testTables table.getn(t2): "..tostring(table.getn(t2)))
    get_console():execute("load ~~~ testTables #t2: "..tostring(#t2))
    amk.dump_table(t2)
    t2[#t2+1] = 7
    t2[#t2+1] = 8
    get_console():execute("load ~~~ testTables table.getn(t2): "..tostring(table.getn(t2)))
    get_console():execute("load ~~~ testTables #t2: "..tostring(#t2))
    amk.dump_table(t2)
    table.remove(t2, 2)
    table.remove(t2)
    get_console():execute("load ~~~ testTables table.getn(t2): "..tostring(table.getn(t2)))
    get_console():execute("load ~~~ testTables #t2: "..tostring(#t2))
    amk.dump_table(t2)

Даёт

! Cannot find saved game ~~~ testtables table.getn(t2): 4
! Cannot find saved game ~~~ testtables #t2: 4
! Cannot find saved game ~~~ testtables table.getn(t2): 2
! Cannot find saved game ~~~ testtables #t2: 2
! Cannot find saved game ~~~ .1 => 2
! Cannot find saved game ~~~ .2 => 4
! Cannot find saved game ~~~ testtables table.getn(t2): 2
! Cannot find saved game ~~~ testtables #t2: 4
! Cannot find saved game ~~~ .1 => 2
! Cannot find saved game ~~~ .2 => 4
! Cannot find saved game ~~~ .3 => 7
! Cannot find saved game ~~~ .4 => 8
! Cannot find saved game ~~~ testtables table.getn(t2): 0
! Cannot find saved game ~~~ testtables #t2: 4
! Cannot find saved game ~~~ .3 => 7
! Cannot find saved game ~~~ .4 => 8

 

Из чего видно, что как только была использована функция table.remove, так сразу разъезжаются результаты table.getn и #, которые до её использования возвращали одинаковые значения, и дальнейшее поведение самой функции table.remove становится некорректным.

Общий вывод такой: конструкцию t2[#t2+1] = 1 можно использовать только в случаях "только для чтения/изменения". В случае надобности удалять элементы таблицы нужно пользоваться стандартными функциями table.insert, table.remove либо переходить на полностью ручное управление таблицей (t2[#t2+1] = 1, t2 = nil, t2 ~= nil и ручной счетчик).

Изменено пользователем sapsan
Ссылка на комментарий

sapsan,

подобное поведение table.remove, table.getn и # похоже на баг старой версии Lua. В новой я такого не наблюдаю, и всё работает достаточно предсказуемо.

 

Однако, я бы сделал оргвыводы. table.remove использовать нельзя вовсе. Никакие манипуляции, изменяющие таблицу в цикле по этой же таблице, совершенно недопустимы.

Возможно, стоит принять идеологию неизменения таблиц-массивов в принципе. Это будет означать, что если надо массив изменить (в смысле добавить или удалить элементы, а не изменить их значения), то надо просто склонировать его, попутно добавив или удалив нужное, а затем заменить ссылку на таблицу на свежесозданную. Это не так страшно, как звучит, поскольку в таблице хранятся не объекты, а ссылки, и клонирование будет поверхностное.

Кроме того, это и не будет намного более затратно, чем тот-же insert и remove, поскольку там внутри происходит примерно тоже самое - перевыделение памяти и копирование массива ссылок на новое место.

Таблицы общего вида (с нецелыми или нерегулярными ключами) менять можно, но опять же не саму себя в цикле. Это категорически нельзя.

 

В защиту этой идеи могу добавить, что многие языки подобную идеологию навязывают (например делая итераторы только для чтения). И не зря, поскольку это существенно надёжнее.

 

 

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Ссылка на комментарий

О, сколько нам открытий чудных...

Пока тут все заняты таблицами, доставляет несказанно следующая картина:

Случилась тут, скажем, с какой нибудь rat_strong31505 неприятность - death_callback. Казалось бы, померла, так померла. Ан нет. issue_event с функцие "update" - еще туда-сюда, а вот try_switch_to_another_section, где тушка пытается посмотреть своими мертвыми глазами на актера, и далее по тексту, в цикле, минимум 2 раза - это, безусловно, сильно.

bar_surprise_box_0009 в качестве npc - это тоже неплохо. Вот кое-где кое-кто жаловался на тормоза на болоте и вообще на новых локациях, так уничтожение всяких ящиков на тормоза влияет так-же, если не сильнее, чем уменьшение плотности тумана.

 

P.S. Кстати, зависаний в xr_logic так и не нашел. Все функции как минимум возвращаются нормально. Как и в каком месте монстры/неписи могут вылетать, увидев врагов - не понимаю. Я не знаю, куда и на что еще смотреть. Логика - scripts\amk\logic\rad_rat1.ltx, scripts\amk\logic\mil_rat1.ltx, scripts\amk\logic\rad_rat2.ltx, scripts\amk\logic\pri_rat4.ltx, scripts\amk\logic\pri_rat5.ltx, scripts\amk\logic\mil_rat2.ltx. Гулаг у всех == nil. Кто-то из них нормальный, а кто-то - вылетает. Кто - не знаю. Лог может закончиться на чем угодно.

 

upd: та, что c припяти -и вылетает.

 

Так, скажите кто-нибудь: эта конструкция -

on_timer = 120000 | mob_home1

on_signal = sig_attacked | mob_combat

- вообще в принципе работает ? Я вижу, что срабатывает всегда только переключение по первому условию. Вряд-ли это имеет отношение к вылету, но тем не менее.

 

И кто вообще разбирается в связках хr_* - state_mgr* ?

Изменено пользователем Dennis_Chikin
Ссылка на комментарий

malandrinus, О как, мы тут уже "философию программирования на LUA" разрабатываем? :)

Существенно надежнее, зато существенно негибче.

 

Стандартный пример - ищем в таблице пока не выполнилось условие,тут же изменяем и break - вот, я отошел от правила,а ничего не напортачил.

 

Не дело это - правила жесткие,давайте еще вообще хэш-таблицы для надежности запретим...

Просто когда делаешь - понимать надо что делаешь, а остальное все - дело техники.И ограничения искусственные не нужны.

 

Вообще к каждому куску кода индивидуальный подход надо,а вы тут все по одной линейке меряете...

Изменено пользователем Monnoroch
Ссылка на комментарий

malandrinus, нет, стандартными функциями пользоваться можно.

    local t2 = {2, 3}
    table.insert(t2, 4)
    table.insert(t2, 5)
    get_console():execute("load ~~~ testTables table.getn(t2): "..tostring(table.getn(t2)))
    get_console():execute("load ~~~ testTables #t2: "..tostring(#t2))
    table.remove(t2, 2)
    table.remove(t2)
    get_console():execute("load ~~~ testTables table.getn(t2): "..tostring(table.getn(t2)))
    get_console():execute("load ~~~ testTables #t2: "..tostring(#t2))
    amk.dump_table(t2)
    table.insert(t2, 7)
    table.insert(t2, 8)
    get_console():execute("load ~~~ testTables table.getn(t2): "..tostring(table.getn(t2)))
    get_console():execute("load ~~~ testTables #t2: "..tostring(#t2))
    amk.dump_table(t2)
    table.remove(t2, 2)
    table.remove(t2)
    get_console():execute("load ~~~ testTables table.getn(t2): "..tostring(table.getn(t2)))
    get_console():execute("load ~~~ testTables #t2: "..tostring(#t2))
    amk.dump_table(t2)

Даёт

! Cannot find saved game ~~~ testtables table.getn(t2): 4
! Cannot find saved game ~~~ testtables #t2: 4
! Cannot find saved game ~~~ testtables table.getn(t2): 2
! Cannot find saved game ~~~ testtables #t2: 2
! Cannot find saved game ~~~ .1 => 2
! Cannot find saved game ~~~ .2 => 4
! Cannot find saved game ~~~ testtables table.getn(t2): 4
! Cannot find saved game ~~~ testtables #t2: 4
! Cannot find saved game ~~~ .1 => 2
! Cannot find saved game ~~~ .2 => 4
! Cannot find saved game ~~~ .3 => 7
! Cannot find saved game ~~~ .4 => 8
! Cannot find saved game ~~~ testtables table.getn(t2): 2
! Cannot find saved game ~~~ testtables #t2: 2
! Cannot find saved game ~~~ .1 => 2
! Cannot find saved game ~~~ .2 => 7

 

Тоесть все функции нормально отрабатывают.

Ссылка на комментарий

Здесь нашел неофициальный мультиплеерный патч 7.02е (как бы 1.0007). Говорится, что для сингла можно использовать из него gamedata.dbe. После установки ловим вылет по отсутсвию секции, которой нет в Соляночном gamedata/config/weathers/flares.ltx. После простого переноса недостающих секций игра запускается. Но это нельзя считать применённым патчем, так как в Солянке будут и другие файлы, которые "родом" из 1.0004 и которые нужно довести до 1.0007 и оставить соляночные изменения.

 

P.S. Сам я это делать уже не буду (так как по-просту нет времени), но не рассказать о такой находке не мог :)

Желающие - дерзайте, там ведь есть исправления оригинальной игры и, кроме того, теоретически можно попробовать взять dll-ки.

 

BadSven, всё есть в ридми в архиве. Или на странице по ссылке. ;)

Как минимум

- пофиксена геометрия l11_pripyat, исчезли фантомные гаражи, проявились ранее невидимые

- пофиксен конфиг аномалии Ржавые волосы [zone_rusty_hair]

 

Сам gamedata.dbe весит под 70 МБ. Скрипты не изменены. Распакуйте да посмотрите сами :)

Изменено пользователем sapsan
Ссылка на комментарий
sapsan, можно поподробней о изменениях именно для сингла? Изменено пользователем BadSven

Уехал на Дальний Восток хватать радиацию

t2.png

Ссылка на комментарий

BadSven, в 1.07 есть единственное изменение, которое было бы интересно для сингла:

- увеличено число стеков памяти выделяемой xr_3da.exe, возможно повлияет на уменьшение вылетов при переполнении памяти

Но, к сожалению, это только для мультиплеера.

Что в конфигах - я пока не сравнивал...

 

TREWKO, можно. Но некрякнутый ехе после этой операции перестанет запускаться, а у крякнутого - это не единственная проблема, к сожалению

 

ЗЫ: Давно бы уже пора GSC выложить хотя бы ехе без старика, я уже не говорю про исходники :D

Изменено пользователем Shadowman

Железо: Intel Core i5 9400F / 16Gb DDR4 2400MHz / SSD NVMe M.2 Samsung 970 EVO Plus 256Gb / GF GTX 1050Ti 4Gb Ось: Win10x64

Ссылка на комментарий

Ха... Возможно, я невнимателен, но ни где этого не видел.

А между тем, выполняя в цикле local result, key, value = ini:r_line("my_section",i,"","") - мы получаем содержимое конфига, отсортированное по key.

 

Это к вопросу о размере и формате конфигов.

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

 

P.S. И, да, не помню, кто писал про сохранность переменных внутри функции при повторном вызове: это была плохая идея.

 

Господа присяжные заседатели !

В рамках лозунга: "Очистим солянку от ... тормозов" - гляньте, кому не лень, товарища aem_arny29193 (или какой там у него номер в ваших сэйвах) на предмет story_id и инвентаря.

 

Тупо перебором 1,65534 и проверкой parent_id.

 

У меня он почему-то коммонер, и по совместительству - бинтовый магнат - владелец половины, если не больше, всех бинтов Зоны.

Возможно, глюк в моем коде - в сборе статистики, а возможно - и не в моем.

 

И неплохо бы сделать ревизию человеков-оркестров.

Ссылка на комментарий

Странности с сохранением 64-разрядных данных.

Решил было исправить сохранение и, соответсвенно, загрузку времени в level_weathers.script с 32-разрядного на 64-разрядное беззнаковое. В луа_хелп такие функции вроде как есть, но с НИ после попытки сохранится получаю безлоговый вылет.

В такой замене функций, как мне кажется, также нуждается скрипт xr_gulag.script

 

malandrinus, я переделал всюду время на 64-разрядный формат (используется game.get_game_time()). Поэтому и нужно хранить 64-разрядное значение. Иначе сохранённое значение будет после переполнения всегда меньше текущего и постоянно будет исполнятся условие необходимости каких-то действий или, если хранится стартовое время, всегда старт + дельта будет меньше текущего времени, что опять же приведёт к постоянному выполнению каких-то действий (наприммер - смена погоды), или эти действия перестанут выполнятся вовсе. Это уже всё зависит от алгоритма...

Изменено пользователем sapsan
Ссылка на комментарий

sapsan,

а смысл? Время в игре всё равно зацикленное. Как 2^32 игровых миллисекунд проходит - отматывается на стартовое значение.

 

Добавлено через 128 мин.:

sapsan,

я переделал всюду время на 64-разрядный формат (используется game.get_game_time()). Поэтому и нужно хранить 64-разрядное значение.

Так а толку, что там 64 бита?! Это время всё равно заворачивается на стартовое после переполнения счётчика. Я проверял.

Но если переделал, то сохраняй по компонентам:

год сохранять не нужно, так как он никогда не изменится.

месяц, день месяца, час, минута, секунда - по одному байту, всего 5

миллисекунды - два байта

итого 7 байт

и сделать пару служебных функций для сохранения/загрузки, и все дела.

 

 

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Ссылка на комментарий
месяц, день месяца, час, минута, секунда ... миллисекунды

Сохранять лучше "натуральные" величины - "год, день, секунда", а "синтетические" вычислять когда надо.

У меня "год, день, секунда" в одно число влезли (при сохранении), а на "мсек" я забил.

Изменено пользователем 7.9

всё легко

Ссылка на комментарий

Я пытался понять, как все это дело работает в xr_logic.script

особенно save_logic/load_logic.

 

Вроде как все работает. Но есть в количестве объектов с уже пожизненно отрицательным временем, и с положительным. И оно вполне может внезапно измениться.

 

P.S. А вылет на собственно сохранении, или потом ?

 

Вылет прямо при сохранении.

По отрицательным значениям - наверное ты читаешь/смотришь на беззнаковые как на знаковые числа. В этом случае первый бит интрепретируется как минус. sapsan

Изменено пользователем sapsan
Ссылка на комментарий
Arhara, lsclon по вылету
LUA error: ...iles\s.t.a.l.k.e.r\gamedata\scripts\amk_anoms.script:512: attempt to index local 'sobj' (a nil value)
в строке 512 размещена функция set_anomaly_status(), которая может получить nil только из одного скрипта - это move_mgr.script в строке 251, где данные для amk_anoms.set_anomaly_status() берутся от её "землячки" функции amk_anoms.get_anomaly_list_for_pos(). То ли проблема в amk_anoms.script, то ли в путях, возле которых спавнятся аномалии.
Ссылка на комментарий

Выявил симптомы появления полупрозрачных иконок в инвентаре. Видимо не справляется проц. Сначала периодически идут кратковременные (от 3 сек и до 30 примерно) фризы без видимой причины. А потом иконки попросту становятся блекло-прозрачными... ;) Попробую завтра разбить игру на два ядра принудительно - может поможет... Отпишусь.

Вот последние строки в лог-файле:

~ save 022
* Saving spawns...
* Saving objects...
* 31470 objects are successfully saved
* Game 022.sav is successfully saved to file 'c:\users\public\documents\stalker-shoc\savedgames\022.sav'
[16-9] get_xml_name for[maingame_pda_msg.xml] returns [maingame_pda_msg.xml]
[16-9] get_xml_name for[maingame_pda_msg.xml] returns [maingame_pda_msg.xml]
[16-9] get_xml_name for[maingame_pda_msg.xml] returns [maingame_pda_msg.xml]
[16-9] get_xml_name for[maingame_pda_msg.xml] returns [maingame_pda_msg.xml]
[16-9] get_xml_name for[maingame_pda_msg.xml] returns [maingame_pda_msg.xml]
[16-9] get_xml_name for[maingame_pda_msg.xml] returns [maingame_pda_msg.xml]
[16-9] get_xml_name for[maingame_pda_msg.xml] returns [maingame_pda_msg.xml]
[16-9] get_xml_name for[maingame_pda_msg.xml] returns [maingame_pda_msg.xml]
[16-9] get_xml_name for[maingame_pda_msg.xml] returns [maingame_pda_msg.xml]
~ save 023
* Saving spawns...
* Saving objects...
* 31478 objects are successfully saved
* Game 023.sav is successfully saved to file 'c:\users\public\documents\stalker-shoc\savedgames\023.sav'
[16-9] get_xml_name for[ui_mm_main.xml] returns [ui_mm_main.xml]
[16-9] get_xml_name for[scroll_bar.xml] returns [scroll_bar.xml]
[16-9] get_xml_name for[message_box.xml] returns [message_box.xml]
- Disconnect
- Destroying level
DestroySingleton::RefCounter: 0
DestroySingleton::RefCounter: 0
DestroySingleton::RefCounter: 0
DestroySingleton::RefCounter: 0
DestroySingleton::RefCounter: 0
Input:  1
Config-file [c:\users\public\documents\stalker-shoc\user.ltx] saved successfully
Destroying Direct3D...
* RM_Dump: textures  : 0
* RM_Dump: rtargets  : 0
* RM_Dump: rtargetsc : 0
* RM_Dump: vs        : 0
* RM_Dump: ps        : 0
* RM_Dump: dcl       : 0
* RM_Dump: states    : 0
* RM_Dump: tex_list  : 0
* RM_Dump: matrices  : 0
* RM_Dump: lst_constants: 0
* RM_Dump: v_passes  : 0
* RM_Dump: v_elements: 0
* RM_Dump: v_shaders : 0
refCount:pBaseZB 1
refCount:pBaseRT 1
DeviceREF: 1

 


256 символов
Ссылка на комментарий

Терминаторы:

 

по результатам экспериментов выяснилось, что в конфигах должно быть health_restore_v = 0.00x (где x может содержать любое разумное количество нолей или не содержать вовсе) для всего подряд. Сколько раз поиском находится - стлько и править. Тогда реакция на остальные параметры чего угодно где угодно станет осмысленной. Иначе скорость регенерации слишком высока, и вражина убивается либо слишком быстро, либо вообще ни как.

 

Та же ситуация, что и с правками по луту.

 

P.S. впрочем, damages.ltx я у себя все равно поправил - в сторону большего разнообразия. ;)

 

Ссылка на комментарий

MAV,

У него нет условий для появления диалога, сам диалог разрешён в логике. Если другие зомбари, которые д.б друзьями ГГ говорят, то и он должен.

Еще 10 лет таких цен, зарплат и пенсий, и вместо переписи населения будет перекличка

Ссылка на комментарий
Гость
Эта тема закрыта для публикации сообщений.
  • Недавно просматривали   0 пользователей

    Ни один зарегистрированный пользователь не просматривает эту страницу.

AMK-Team.ru

×
×
  • Создать...