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

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

"Работает нормально" - не находишь подобное определение смахивающим на "лишь бы работало - а остальное не важно"?

Цель замечания как раз в том, чтобы не просто "лишь бы работало", а все же как правильно писать скрипты/алгоритмы ...

Привести тебе примеры ситуаций? Да возьми половину игроков, которые таскают в рюкзаках десятками-сотнями пачки патронов, аптечек, жратвы и т.п. И при подсчете веса для каждого из этой сотни предметов идет чтение конфигов и подсчет ... Это ты называешь нормально? Тогда уж давай в кодах исключим опереторы умножения и деления и бум "нормально" складывать и вычитать... :crazy:

На апдейтах то как раз многие и применяют подобное, посмотри в модах "ограничители" веса. Если же делать такие проверки "как бы разово", например на коллбэках "on_take", то представь какая катавасия будет, если взять из трупа/ящика "все разом". т.е. когда циклы перебора предметов инвентаря вызываются не один раз... ;-)

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

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

Под "нормально" я имею ввиду что производительность страдает в пределах нормы (если вешать не на апдейт, а на коллбеки). Ну наблюдаем небольшую задержку при взятии бальшой-бальшой кучи предметов. Терпимо. Как при переходе нескольких сталкеров в онлайн. А чтобы пачек патронов слишком много не было, то надо перепаковщик. И никак не будет сотен пачек патронов.

 

"Работает нормально" - не находишь подобное определение смахивающим на "лишь бы работало - а остальное не важно"?

Нахожу. И чё дальше?

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

Есть же coroutine.

Можно растянуть по времени взятие такого количества единиц предметов.

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

А дальше, раз уж назвался груздем, стОит довести предлагаемый код до "ненормального" состояния:

а) добавить отсутствующую функцию find_symb, без которой и нормально то воспользоваться кодом невозможно ...

б) учтя замечания, добавить кеширование ...

в) несложными добавками снять лейбл "only CoP"

- вот тогда определение "нормально" вполне подойдет для "школьного" примера и в качестве урока "Учимся определять вес инвентаря" для соотв.топика. ;-)

 

Gun12, перепрочти затронутую тему ... Какое тут coroutine? Ты собираешься движку сказать ... подождика до следцующего цикла апдейта, мы еще эти взятые предметы не обработали ... ;-)

 

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

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

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

чистая ТЧ 1.0004

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


...................
local np = net_packet()
sobj:UPDATE_Write(np)
if np == nil then
return nil
end

local table_param = {}
local clsid_sobj = sobj:clsid()
np:r_seek(0)
if clsid_sobj == clsid.wpn_ak74_s or clsid_sobj == clsid.wpn_groza_s then
np:r_seek(2)
elseif clsid_sobj == clsid.wpn_shotgun_s or clsid_sobj == clsid.wpn_bm16_s or clsid_sobj == clsid.wpn_rg6_s then
np:r_seek(?????)
else
np:r_seek(1)
end

table_param = {["upd_condition"] = np:r_u8(),
["upd_weapon_flags"] = np:r_u8(),
["upd_ammo_elapsed"] = np:r_u16(),
["upd_addon_flags"] = np:r_u8(),
["upd_ammo_type"] = np:r_u8(),
["upd_weapon_state"] = np:r_u8(),
["upd_weapon_zoom"] = np:r_u8()}

if table_param["upd_weapon_state"] == 3 then
local msg = "Перезаряжаем"
news_manager.send_tip(db.actor, msg, nil, nil, 30000)
end
.................

 

Для всего оружия кроме дробовиков работает вроде нормально, а вот для дробовиков нет - не могу понять какое значение смещения в np:r_seek(?????) надо выставить.

Подскажите, кто знает ?

Изменено пользователем ColR_iT
Про спойлер так же не забываем.
Ссылка на комментарий

Все же уточню, дабы и другие не наступали на те же грабли ..

Для всех оружейных классов, кроме "с подствольниками" ( "cse_alife_item_weapon_magazined_w_gl") оружейные параметры в нет-пакете начинаются с параметра 'condition'. Для классов с подствольниками - впереди имеется параметр 'grenade_mode' (u8)

.

В примере кода AndreySol, все ошибочно.

1. Читать "оружейные" байты следует не от самого начала нет-пакета, а после секции параметров 'cse_alife_inventory_item'. Учитывая, что довольно затруднительно навскидку определить их кол-во - гораздо легче брать байты не сначала, а с конца прочитанного пакета.

2. Для подствольников после параметров от 'cse_alife_inventory_item' требуется смешение +1 (u8), а не +2, для остальных - 0.

Ничем в этом случае "дробовики" (класс 'cse_alife_item_weapon_shotgun') не отличаются от остальных, просто у них есть свой заключительный параметр 'ammo_ids', который в данном примере кода не читается и не влияет на результат.

'cse_alife_inventory_item'. 'cse_alife_inventory_item'.

 

P.S. Для чего изобретать свой велосипед? ... и не имея навыков по теме, даже не смотреть на уже готовые примеры...

Изменено пользователем Artos
  • Нравится 2

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

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

P.S. Для чего изобретать свой велосипед? ... и не имея навыков по теме, даже не смотреть на уже готовые примеры...

Не соглашусь :) Если бы никто не занимался изобретением велосипедов, то в моддинге давным-давно остались бы единицы, для пересчета которых хватило бы пальцев одной руки. Не приходило ли вам в голову, что многим может быть процесс самостоятельного познания и поиска интереснее, чем получение конечного результата?

 

 

  • Нравится 1

Мод, где не бывает одинаковых путей - Судьба Зоны. (Лучшее, что у меня получилось на X-Ray) На базе модифицированного движка OGSR Engine.

Бывший мододел на X-Ray / Начинающий игродел на Unreal Engine. Программист.

AMD Ryzen 9 7950X (16 ядер, 32 потока, 5.75 ГГц); RTX 3080; 128 ГБ DDR5; Arctic Liquid Freezer II-420; 3 ТБ SSD PCIe 4.0; 4ТБ HDD.

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

Подправил код, все нормально работает.

 

local clsid_sobj = sobj:clsid()
np = net_packet()
sobj:UPDATE_Write(np)
if np == nil then
return nil
end
np:r_seek(0) -- уст. позицию чтения данных в начало нет-пакета --
if clsid_sobj == clsid.wpn_ak74_s or clsid_sobj == clsid.wpn_groza_s then
-- для 'cse_alife_item_weapon_magazined_w_gl' --
table_param = {["upd_grenade_mode"] = np:r_u8()}
end
-- для остальных серверных классов --
table_param = {["upd_current_fire_mode"] = np:r_u8(),
["upd_condition"] = np:r_u8(),
["upd_weapon_flags"] = np:r_u8(),
["upd_ammo_elapsed"] = np:r_u16(),
["upd_addon_flags"] = np:r_u8(),
["upd_ammo_type"] = np:r_u8(),
["upd_weapon_state"] = np:r_u8(),
["upd_weapon_zoom"] = np:r_u8(),
["upd_ammo_current"] = np:r_u16()}

 

С дробовиками то-же вроде нормально. Просто проверял из всех параметров только интересовавший меня на тот момент "upd_weapon_state" на значение 3 - это перезарядка, а оно для дробовиков почему-то не выставляется. Хотя другие значения вроде норм.

 

Artos'у

Не очень понял, отчего-же "все ошибочно" если работает нормально ?

 

"читать байты следует не от самого начала нет-пакета, а после секции параметров 'cse_alife_inventory_item'" - Вы наверное не обратили внимания, что используется UPDATE_Write, для заполнения нет-пакета, а он похоже не читает 'cse_alife_inventory_item'.

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

AndreySol, читает-читает. Если скрипт выдает похожие на правду значения - это случайность. Учитывать cse_alife_inventory_item - обязательно.

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

Zander_driver

Не приходило ли вам в голову, что многим может быть процесс самостоятельного познания и поиска интереснее, чем получение конечного результата?

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

Собственно и фраза эта имеет подтекстом не прямое толкование, а аллегорию о:

«Изобретать велосипед» — пытаться изобрести заново конструкцию, которая уже давно всем известна, отлично отработана, и совершенна в том смысле, что не содержит практически ничего лишнего и полностью соответствует своим задачам. Иногда вместо слова «велосипед» употребляется слово «колесо».

Познание - это совершенно иное и в-первую очередь как раз и подразумевает изучение/постижение уже доступных знаний и на их базе (если годятся) - продвижение вперед.

 

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

О каком познании и самостоятельности тут можно вести речь? Уже десяток раз тут повторялось именно в адрес автора вопроса - читаем статьи и изучаем ФАК, дабы не спрашивать в 'дцатый раз одно и то же ...

 

 

 

AndreySol, у нас с тобою диаметрально противоположные понятия к слову "нормально" ... Когда ты все же поймешь что-такое нет-пакет, его формат и правила его чтения/записи - тогда поймешь, что в твоем случае была нормальная ошибка наступившего в очередной раз на грабли. Расписывать тут статью про нет-пакеты не вижу необходимости и смысла, все есть на вики-сайтах.

 

Вы наверное не обратили внимания, что используется UPDATE_Write, для заполнения нет-пакета, а он похоже не читает 'cse_alife_inventory_item'.

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий
... отчего-же "все ошибочно" ...?

раз раздел "Школа" - устроим небольшой разбор "полетов":

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

- на какой ляд эти строки(?):

if np == nil then	
return nil	
end

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

- далее:

table_param = {["upd_grenade_mode"] = np:r_u8()}

- поздравляю, все параметры нет пакета пакет уместились в один ... :wacko2:

- еще далее - эта же таблица затирается новыми "нормальными" значениями ...

ну что тут можно сказать ... как вообще у Вас это "работает" и не вылетает, разве только то, что читаете абы какие байты и в результате все одно не важно - заряжает/перезаряжает иль вообще ничего не делает.

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

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

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

- далее:

table_param= {["upd_grenade_mode"] = np:r_u8()}

- поздравляю, все параметры нет пакета пакет уместились в один ...

 

почему в один ?

Цитата из "Справочника ..." : "Значение читается из буфера начиная с текущей позиции чтения, а позиция чтения увеличивается на размер читаемого значения.

.....

8, 16, 24, 32, 64 - один, два, три, четыре, восемь байт соответственно

Устанавливаем позицию чтения в 0: np:r_seek(0), затем читаем один байт, указатель смещается на этот 1 байт.

Что-ж тут неправильного ?

 

- еще далее - эта же таблица затирается новыми "нормальными" значениями

Очепятался, бывает. Поздно было, не доглядел. Исправил уже.

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

Первый вопрос: Как отследить class id оружия из которого было произведено убийство? Просто как не бился все равно вылетает "actor79", и кстати почему 79, а в lua_help.script указан индекс равный 78?

 

Второй вопрос: Как можно перенести менеджер тайников из ЗП в ТЧ? Или написать что-то подобное?

 

Третий вопрос: Есть ли 'hit callback' для актора, делал по аналогии - ничего не работало, его действительно нет, или я что-то не так делаю?

 

Версия игры: ТЧ 1.0004

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

Все-же хочу разобраться с нет-пакетами.

 

 

Сейчас код выглядит так:

local table_param = {}
local clsid_sobj = sobj:clsid()
np = net_packet()
sobj:UPDATE_Write(np)
np:r_seek(0) -- уст. позицию чтения данных в начало нет-пакета --
if clsid_sobj == clsid.wpn_ak74_s or clsid_sobj == clsid.wpn_groza_s then
-- для 'cse_alife_item_weapon_magazined_w_gl' --
table_param["upd_grenade_mode"] = np:r_u8()
end
-- для остальных серверных классов --
table_param["upd_current_fire_mode"] = np:r_u8()
table_param["upd_condition"] = np:r_u8()
table_param["upd_weapon_flags"] = np:r_u8()
table_param["upd_ammo_elapsed"] = np:r_u16()
table_param["upd_addon_flags"] = np:r_u8()
table_param["upd_ammo_type"] = np:r_u8()
table_param["upd_weapon_state"] = np:r_u8()
table_param["upd_weapon_zoom"] = np:r_u8()
table_param["upd_ammo_current"] = np:r_u16()

Делаю проверку для АК-74, в мегазине 25 простых патронов, навешен подствол (не заряженный), в инвентаре есть пачка на 15 БП к нему.

Значения, полученные для него: upd_grenade_mode = 0, upd_ammo_elapsed = 25, upd_addon_flags = 2, upd_ammo_type = 0, upd_weapon_zoom = 0.

Отстреливаю 5 патронов - upd_ammo_elapsed = 20, перехожу в режим прицеливания - upd_weapon_zoom = 1. Затем переключаюсь на подствол - upd_grenade_mode = 1, upd_ammo_elapsed = 0. Перезаряжаю подствол - upd_ammo_elapsed = 1. Далее возвращаюсь в режим обычной стрельбы и перезаряжаюсь со сменой типа патронов - upd_ammo_elapsed = 15, upd_ammo_type = 1.

Для пистолета и СПАС-12 все параметры то-же соответствуют реальности. С upd_weapon_state пока досконально не разбирался, сложно все флаги отследить.

 

Разве можно так случайно и неверно читать данные из нет-пакета, чтобы "ошибочно" получать такие адекватные значения ?

 

 

Осталось пока несколько непоняток:

одна глобальная - в чем разница между State и Update частями пакета - думаю что State используется для сохранения состояния объекта при сохранении самой игры, а Update для синхронизации клиентской и серверной частей обекта в процессе игры. ???

 

С upd_weapon_state. Проверял этот параметр просто по числовому значению, опытным путем выяснил, что 3 соответствует перезарядке для всех оружий, кроме дробовиков(cse_alife_item_weapon_shotgun). 0 - idle-состояние, 6 - оружие убрано(strapped). Понимаю что этот параметр - набор битовых флагов, знать-бы их раскладку в соответствии с состояниями оружия.

 

С upd_current_fire_mode - по идее должен отражать в себе режим стрельбы ? Почему-то всегда 0.

 

upd_ammo_current - что вообще означает ? Текущий патрон в стволе ? Имеет 2 байта - что в них ?

 

 

 

 

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

Srtuck

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

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

 

2. Можно, написав подобное. Дерзай.

 

3. Извини, но 'hit callback' - это нечто из твоих додумок и простому смертному аналогию провести сложно, тем более еще чтобы и работало. Проясни для нас дремучих, если ответ еще восстребован.

 

 

AndreySol, хотеть не вредно, но разбираться в твоих гаданиях на кофейной гуще лучше делать не в топике по скриптам... Ничего общего с темой топика это не имеет.

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

Укажу только на то, что для других может иметь смысл и значение:

1. При получении чистого нет-пакета ( pk = net_packet() ) важно(!) точно знать где установлена позиция записи ( pk:w_tell() ), т.к. последующая запись параметров объекта (в данном случае оружия) будет записываться именно с этим смещением. Если для чистого ТЧ это значеник как правило равно 0, то для ЧН/ЗП они нередко совершенно иные. Да и ... для ТЧ ничто не гарантирует, что будет записываться именно с нулевой позиции.

Т.о. нормальный программер/модмейкер сам установит позицию чтения (например pk:begin(0) ) и будет считывать именно от установленной позиции (в примере это будет +2 => pk:r_seek(2) ), а не полагаться на удачу ...

 

2. Как ранее тут говорилось, для оружия update-параметры начитаются с параметров класса 'cse_alife_inventory_item' и первым идет параметр 'num_items' (название условное). Этот параметр имеет размер в один байт (h8) и в общем случае как правило равен 0. В этом случае остальные параметры секции отсутствуют, но это частный(!) случай.

 

Т.о. в примере потуг написать код AndreySol выходит следующее:

1. Учитывая, что он кодит для ТЧ, параметры в нет-пакет дефолтно записываются с нулевой позиции, что не гарантированно для вариаций других движков.

2. Допуская очередную ошибку в последовательности чтения байтов из пакета, т.е. считывая в самом начале некий однобайтовый 'upd_current_fire_mode' - тем самым считывается именно 'num_items' ... и при условии равенства его нулю, все дальнейшее уже идет по порядку. Если 'num_items' не будет равен 0, то все дальнейшее накрывается медным тазом...

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

 

Вот так, совершая ошибки и глупости, можно получать вроде как "нормальные" результаты, а потом гадать и в очередной раз вопрошать в форумах, отчего все так забаговано ... :crazy:

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий
установит позицию чтения (например pk:begin(0) ) и будет считывать именно от установленной позиции (в примере это будет +2 => pk:r_seek(2) ),

pk:begin(0) - видимо очепятка, а использование r_begin у меня приводит к подвисанию и вылету. Разве r_seek не устанавливает новую позицию чтения по любому с 0 ?

 

Код исправил, теперь выглядит так:

se_obj:UPDATE_Write(np)

np:r_seek(2)

 

table_param["upd_condition"] = np:r_u8()

table_param["upd_weapon_flags"] = np:r_u8()

table_param["upd_ammo_elapsed"] = np:r_u16()

table_param["upd_addon_flags"] = np:r_u8()

table_param["upd_ammo_type"] = np:r_u8()

table_param["upd_weapon_state"] = np:r_u8()

table_param["upd_weapon_zoom"] = np:r_u8()

table_param["upd_current_fire_mode"] = np:r_u8()

 

if clsid_sobj == clsid.wpn_ak74_s or clsid_sobj == clsid.wpn_groza_s then

table_param["upd_grenade_mode"] = np:r_u8()

end

Для оружия с подстволами значения нормальные, кроме "upd_grenade_mode" - всегда 0.

Опять что-то я не правильно понял ?

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

Когда жы ты прежде чем делать руками будешь читать написанное и думать? :-)

 

1. pk:begin(0) - опИска, в реальном коде это должно быть pk:w_begin(0), что легко посмотреть и уточнить в lua_help.script.

2. pk:w_begin(0) - устанавливает позицию записи(!) в начало, записывая именно в начало (с 0-ой позиции) первые два байта, которые потом следует учитвать (отсекая pk:r_seek(2) ).

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

3. Твой "исправленный" код вновь полностью ошибочен, ты просто пытаешься методом бездумного тыка получить желаемое, но ... это не цифирьки конфига и пока ты не поймешь как нужно и не сделаешь все как дОлжно - будешь мыкаться и удивляться что мол "вот только с этим не так и в этой ситуации не эдак".

 

И убирай, плз, портянки кодов под спойлер и соответствующий кодам тэг.

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

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

P.S. Чтобы не мусолить далее эту тему, вот тебе заготовка, для частного случая, когда num_items == 0:

local np = net_packet() --/ получаем 'чистый' нет-пакет
np:w_begin(0) --/ писАть будем в самое начало (+2 байта)
se_obj:UPDATE_Write(np)
np:r_seek(2) --/ ставим чтение на 3-й байт, пропуская первые два

table_param = {} --/ писать параметры будем сюда
local num_items = np:r_u8() --/ первый параметр секции 'cse_alife_inventory_item'
if num_items == 0 then --/ если 0 - то далее следуют 'оружейные' параметры
 --/ для 'с подствольниками' считываем их первый параметр
 if clsid_sobj == clsid.wpn_ak74_s or clsid_sobj == clsid.wpn_groza_s then
   table_param["upd_grenade_mode"] = np:r_u8()
 end
 --/ читаем общие для всего оружия параметры
 table_param["upd_condition"] = np:r_u8()
 table_param["upd_weapon_flags"] = np:r_u8()
 table_param["upd_ammo_elapsed"] = np:r_u16()
 table_param["upd_addon_flags"] = np:r_u8()
 table_param["upd_ammo_type"] = np:r_u8()
 table_param["upd_weapon_state"] = np:r_u8()
 table_param["upd_weapon_zoom"] = np:r_u8()
 table_param["upd_current_fire_mode"] = np:r_u8()
else
 --/ читать пакет нужно более продвинутым способом!
end

 

Также, советую хорошенько полумать и понять разницу между параметрами из update-пакета и state- ... Читать без причины, например, кол-во патронов в стволе (ammo_elapsed) из update- и ошибочно и не правильно.

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

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

Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий

Комментарии могут оставлять только зарегистрированные пользователи

Создать аккаунт

Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!

Зарегистрировать новый аккаунт

Войти

Есть аккаунт? Войти.

Войти
  • Недавно просматривали   0 пользователей

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