Kirgudu 1 264 Опубликовано 19 Августа 2020 Начинающего ковыряльщика может интересовать вовсе даже не ТЧ, а, скажем, ЧН, как меня 9 лет назад, или ЗП. Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 12 Сентября 2020 19 часов назад, Norman Eisenherz сказал: Работает ли метод iterate_inventory_box(func, obj) в ЧН? Работает. Применяется, например, в моде OGSM CS 1.8 CE Fixes для переноса вещей из ящика в инвентарь актора после миниигры со стрельбой. Насколько мне известно, работает без ошибок. 1 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 23 Сентября 2020 @_Sk8_AsTeR_, судя по коду, речь о модуле Артоса? Можно, только не в стандартные свойства нет-пакета для данного объекта, а в его кастом дату. Например, при взятии артефакта в инвентарь я успешно добавлял признак того, что артефакт уже был найден (для исключения повторного учёта в статистике): Скрытый текст function on_artefact_take(obj) local s_obj = alife():object(obj:id()) if s_obj then local pk = get_netpk(s_obj, 1) if pk:isOk() then local data = pk:get() local tbl = data.custom_data:getTable() if not tbl.artefact_found then xr_statistic.inc_founded_arts_counter() tbl.artefact_found = {} data.custom_data:setTable(tbl) pk:set(data) end end end end Для понимания: в данном случае присвоенная свойству artefact_found пустая таблица превращается в кастом дате, представленной строкой, в секцию [artefact_found] без дочерних элементов. 1 1 4 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 23 Сентября 2020 Вот чтобы не "убились", и надо задействовать кастом дату. В описанном случае никаких неприятных последствий замечено не было. 1 2 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 23 Сентября 2020 (изменено) @Zander_driver, я имел в виду несколько другое. Если выбирать между записью в кастом дату и в отдельное свойство всего нет-пакета [ local data = pk:get() data.my_prop = 1 pk:set(data) ] - однозначно следует предпочесть кастом дату, поскольку добавление отдельного свойства может поломать весь нет-пакет, обладающий определённой структурой для каждого типа объекта (хотя не исключено, что модуль просто проигнорирует добавленные свойства, не характерные для нет-пакета - это я не проверял). Ну а то, что мы не можем превышать определённую длину, обсуждалось уже много раз. Впрочем, согласен, упомянуть об этом стоило. Изменено 23 Сентября 2020 пользователем Kirgudu 1 1 2 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 18 Октября 2020 @Norman Eisenherz, game_relations.set_squad_goodwill(squad_id, "enemy"). И вообще, стоит поизучать этот модуль и его применение в других скриптах и логике. Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 19 Октября 2020 (изменено) @Norman Eisenherz, достаточно определить, что командир отряда стал враждебным, ведь метка отряда вешается на него. См. commander:general_goodwill(db.actor) в модуле sim_squad_generic.script (commander определяется там же) и дальнейшее использование этого показателя. При определённых его значениях можно вызывать self:hide() / self:show(), что приведёт к нужному результату. Изменено 20 Октября 2020 пользователем Kirgudu была ошибка в названии метода Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 12 Декабря 2020 (изменено) @UriZzz, предлагаю борьбу с невнимательностью и fps продолжить дальше и поднять не невиданный доселе уровень, увеличив твою опытность ещё больше. Смотри. Функция у тебя с говорящим названием, sleep(obj), предназначена теоретически только для обработки нажатия на спальный мешок. Не знаю, откуда и как она вызывается, но если проверка на то, что ты используешь именно спальник, до вызова функции есть, тогда условие if obj:section() == "sleep_bag" then является лишним. Но скорее всего такую проверку ты до функции не делаешь, а просто всегда дёргаешь её в коллбэке на дроп (ТЧ) или использование предмета (ЧН, ЗП). Примем это допущение, и тогда возникает другой момент. Что будет, если вокруг тебя на расстоянии 40 метров нет ни одного врага? А если ты съел колбасу? Правильно, проверка на врага сработает, а поскольку рядом никого нет, пройдёт по полному циклу, по всем 65 с лишним тысячам потенциальных объектов. И в результате ты, может, и избавился от тормозов при выдаче сообщения, зато приобрёл их при любом использовании любого предмета (если только ты не ставишь целью кушать, применять антирад, использовать бинты и аптечки и т. д. также только в спокойном месте). Выходом является перемещение поиска врагов после условия if obj:section() == "sleep_bag" then, так чтобы цикл запускался только если ты используешь нужный предмет. И последнее, чисто перфекционистское замечание. Если всё, что делает функция, это проверяет, можешь ли ты использовать спальник, и показывает нужный диалог или выдаёт сообщение, тогда нет нужды заморачиваться с лишними брейками и переменными. Можно выдать сообщение и сразу выйти из функции (return сработает как и break, прервёт выполнение цикла, но вдобавок ещё и обеспечит выход), а меню будет показано за пределами цикла, если всё хорошо, и прерывания не случилось. Самое время проиллюстрировать вышесказанное. Скрытый текст function sleep(obj) -- мы ещё и условие проверки перевернём: если сработал не спальник, сразу выйдем из функции - дальнейшая портянка нас не интересует if obj:section() ~= "sleep_bag" then return end -- не спальник --> выход -- ogse.spawn_item_in_inv("sleep_bag") -- по-хорошему, спавнить новый предмет лучше сразу, чем разбивать на 2 части, при выдаче сообщения и, видимо, где-то в недрах класса спальника for k=0,65534 do local m_obj = level.object_by_id(k) -- здесь проверку на m_obj прикрутим спереди к остальным; все критерии срабатывают последовательно, так что ошибки не будет -- это позволит нам не множить "if" и не увеличивать кол-во уровней вложенности условий if m_obj and ((IsStalker(m_obj) and ogse.get_npc_relation(m_obj,db.actor)=="enemy") or IsMonster(m_obj)) and m_obj:position():distance_to(db.actor:position()) < 40 and m_obj:see(db.actor) then ogse.send_tip("Не получится заснуть пока вокруг шляются всякие", "Меченый", 0, 10, "mecheny") ogse.spawn_item_in_inv("sleep_bag") -- если не заспавнили выше return --> и сразу выход из цикла и функции end end -- если всё хорошо и цикл врагов не выявил, ничто больше не мешает показать меню спальника local hud = sleep_ui(get_hud()) -- указываем на class "sleep_ui" (CUIScriptWnd) level.start_stop_menu(hud, true) -- открываем меню end Результат: избавились от лишних времязатратных действий, укоротили (если стереть мои комментарии) код вдвое, а также малость улучшили читабельность. P.S. При желании ты с Lua разберёшься, я уверен. С СДК разобрался, значит и со скриптами сможешь. Надо лишь пройти чуть дальше, чем "работает - и ладно". @Марка демченков, попробуй это: exit() Изменено 12 Декабря 2020 пользователем Kirgudu 1 5 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 12 Декабря 2020 @UriZzz, ты, главное, принцип запомни. Пойми суть предложенных тебе изменений. А чем дальше, тем проще будет. 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 6 Февраля 2021 @UriZzz у тебя и подсказка в логе есть args=[string]~not_table! и пример в конце модуля start_game_timer(3*60, nil, {info_id = "my_infoportion"}) Грубо говоря, ты в качестве доп. аргумента передаёшь строку "UriZzz_test.mecheny_mail", а надо таблицу. То есть: start_game_timer(30*60, nil, {param1 = "UriZzz_test.mecheny_mail"}) -- аргумент - таблица Если же ты хотел вызвать функцию внешнего модуля (на что слегка намекает текст "UriZzz_test.mecheny_mail"), то для этого надо было воспользоваться вторым аргументом, который у тебя сейчас равен nil, и без кавычек. А именно: start_game_timer(30*60, UriZzz_test.mecheny_mail) -- аргумент - указатель на функцию внешнего модуля В общем, смотри внимательно примеры в конце модуля таймеров, там всё расписано. 1 1 2 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 9 Февраля 2021 45 минут назад, Colder сказал(а): Подскажите функцию for k,v in pairs(бла) do if v == true then db.actor:give_game_news('бла-бла', 'бла-бла-бла', "ui_iconsTotal_PDA", 0, 3000) end end P.S.: задавай свои вопросы в человекопонятной форме. 1 2 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 9 Февраля 2021 @h0N0r все перечисленные методы действительно клиентские, а в переменной obj у тебя серверный объект. Если хочешь получить клиентский, следует действовать например так: local cobj = level.object_by_id(obj.id) if cobj then ... end и далее по написанному. Однако зачем делать это после удаления, если я правильно тебя понял? Ты уж определись, что необходимо - удалить объект или придать ему ускорение. 1 1 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 23 Марта 2021 (изменено) 54 минуты назад, ted.80 сказал(а): Что-то ме подсказывает что id тут лишнее попробуй так Не надо так делать, в том варианте должно быть именно sobj.id. А так гейм вертекс можно (и нужно в данном случае) получать уже из серверного объекта: local sobj = alife():object(i) if sobj and sobj.m_game_vertex_id == 2482 and IsStalker(sobj) and sobj:alive() then return true end И ещё: почему только 2482? Других вертексов на нужной локации нет? Имхо, лучше из гейм вертекса получать id локации и проверять уже его совпадение с нужным: function get_level_nps() local al, gg = alife(), game_graph() -- многократно используемые функции кешируем для производительности for i=1,65535 do local sobj = al:object(i) if sobj and gg:vertex(sobj.m_game_vertex_id):level_id() == XXX and IsStalker(sobj) and sobj:alive() then -- вместо XXX подставить Id локации (не путать с наименованием) return true end end return false end Или, чтобы не вызывать лишние функции, сравнивать sobj.m_game_vertex_id с диапазоном значений - больше одного и меньше другого: if sobj and sobj.m_game_vertex_id >= XXX and sobj.m_game_vertex_id <= YYY and IsStalker(sobj) and sobj:alive() then -- вместо XXX и YYY подставить граничные гейм вертексы локации return true end Изменено 23 Марта 2021 пользователем Kirgudu 1 1 2 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 30 Апреля 2021 5 часов назад, Капрал Хикс сказал(а): Почему-то повторяются функции function add_obj( obj ) и function del_obj( obj ) и мне это кажется странным. Такое вообще допустимо? Как ни странно, да. Примеры двойного объявления одних и тех же функций встречаются даже в скриптах оригинала (хотя, может быть, это-то как раз и не странно). Если кому интересно - загляните в чистонебовский скрипт task_objects.script, функция CHideFromSurgeTask:check_task(). Там внутри есть две встроенные функции, описанные дважды в пределах одного пространства. На практике, если представить, что содержимое повторяющихся функций различно, работать будет та, которая объявлена второй (третьей, четвёртой и так далее). Что конкретно должно быть в примере выше, сказать не могу. Всё зависит от логики, которую хотелось вложить в код автору. Возможно, заполняться должна только таблица creatures, возможно - creature, а возможно и обе сразу. Надо изучать те скрипты, где они используются далее. Но я предлагаю критически взглянуть на другое место. Вот: function add_obj( obj ) -- ... <skip> ... if IsStalker(obj) and IsMonster(obj) then --> если И сталкер И монстр btr_target[obj:id()] = true end end Ничего не смущает? Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 29 Августа 2021 (изменено) 11 часов назад, AndrewMor сказал: Вообще-то, это тема по ТЧ, если что. С каких пор? Может, уже появились альтернативные темы по всем трём платформам, а народ-то и не в курсе? Тема по ТЧ - это "[SoC] Ковыряемся в файлах" или, например, "[SOC] Мелкие правки движка". "Скриптование" же всегда было мультиплатформенной темой, не надо искусственно навязывать лишние рамки. @Norman Eisenherz но тема всё равно вряд ли правильная, с таким вопросом, имхо, надо идти к тем, кто ковыряет движок. Изменено 29 Августа 2021 пользователем Kirgudu 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 30 Декабря 2021 (изменено) 29.12.2021 в 02:59, Jekyll сказал: Как передать предмет неписю от актора не по секции, а по id? Например, распотрошить упомянутую функцию relocate_item_section_from_actor и переделать её под использование id: Скрытый текст function relocate_item_from_actor_by_id(first_speaker, second_speaker, id) if not id then return end local function who_is_npc(first_speaker, second_speaker) if db.actor:id() == second_speaker:id() then return first_speaker else return second_speaker end end local npc = who_is_npc(first_speaker, second_speaker) local function transfer_item(item) if item:id() == id then db.actor:transfer_item(item, npc) news_manager.relocate_item(db.actor, "out", item:section()) end end db.actor:inventory_for_each(transfer_item) end Изменено 30 Декабря 2021 пользователем Kirgudu 2 5 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 10 Января 2022 (изменено) 25 минут назад, INNOCENT KILLAZ сказал: они одноразовые или нет Нет, конечно. Это точки постоянного (на протяжении игры) периодического (раз в какое-то время) спавна в указанной точке указанной группы монстров с контролем максимальной численности. 25 минут назад, INNOCENT KILLAZ сказал: что дает "fake" См. в функции ogsm_packet.spawn_monster. В зависимости от значения в этом параметре ("fake"/"random_fake"/прочее) монстру назначается та или иная кастомная логика поведения. На будущее, подобные вопросы больше подходят для одной из тем "Ковыряемся в файлах" (в данном случае, я так подозреваю, вариация для ЧН). Изменено 10 Января 2022 пользователем Kirgudu 1 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 11 Января 2022 (изменено) @INNOCENT KILLAZ да, фриплей тут ничем концептуально не отличается. Однако набор и наполнение точек могут меняться на разных стадиях игры, в том числе при наступлении фриплея - см. для подробностей код модуля ogsm_respawn. Там есть проверки по выданным инфопорциям и в зависимости от этого разные наборы спавна. Изменено 11 Января 2022 пользователем Kirgudu 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 5 Февраля 2022 (изменено) @Colder конечно, если вместо случайной выборки одной строки воспользоваться, например, циклом и вернуть по итогу таблицу (не забыть обработать её на выходе отличным от пары значений образом): Скрытый текст --local key = math.random(0,n-1) --local result, item, num = ini:r_line("generic_list",key,"","") --alife():create(item, db.actor:position(), db.actor:level_vertex_id(), db.actor:game_vertex_id(), db.actor:id()) --return item, num local t = {} for key = 0,n-1 do local result, item, num = ini:r_line("generic_list",key,"","") alife():create(item, db.actor:position(), db.actor:level_vertex_id(), db.actor:game_vertex_id(), db.actor:id()) table.insert(t, { item = item, num = num }) end return t Так будут обработаны все строки из generic_list. При желании сюда же можно прикрутить случайную выборку нескольких строк и так далее. Простор для творчества не ограничен. Изменено 5 Февраля 2022 пользователем Kirgudu 1 1 Инструмент Поделиться этим сообщением Ссылка на сообщение
Kirgudu 1 264 Опубликовано 8 Июля 2022 По мотивам всего вышенаписанного. 06.07.2022 в 10:28, HellRatz сказал: shape0:axis_x = 2.64159965515137,0,0 --ширина зоны по X shape0:axis_y = 0,2.22759985923767,0 --ширина зоны по Y shape0:axis_z = 0,0,2.64159965515137 --ширина зоны по Z shape0:offset = 0,0,0 --поворот по осям (x,y,z) Лишний раз хотелось бы заметить, что подобные советы, по сути своей возможно и правильные, могут быть крайне вредны, если даются новичку, за недостатком опыта не отличающему комментарий в коде от комментария в сообщении. Если уж решил помочь, лучше потрудиться и написать текст, не оставляющий места для кривотолков. @Zander_driver, респект. 1 1 1 Инструмент Поделиться этим сообщением Ссылка на сообщение