Dennis_Chikin 3 658 Опубликовано 23 Августа 2015 Поделиться Опубликовано 23 Августа 2015 Ужасно. Неизвестно что делается неизвестно когда с неизвестно чем. Ну и что хотим получить в результате ? Еще раз подумать над вот этим вот вопросом, а потом уже думать, как это сделать. Очевидно, что "есть" ничего не надо совсем. Ну и темку про использование предметов почитать. 1 Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Ссылка на комментарий
antihumanist 0 Опубликовано 24 Августа 2015 Поделиться Опубликовано 24 Августа 2015 Ужасно. Неизвестно что делается неизвестно когда с неизвестно чем.Вот переделал все для демонстрации бага на стандартных вещах и без "лишних" функций.Вызов бага показан в функции test_bug.Остальное привел для полноты данных. --Добавление нового колбека в bind_stalker.script function actor_binder:reinit() object_binder.reinit(self) local npc_id = self.object:id() db.storage[npc_id] = { } self.st = db.storage[npc_id] self.st.pstor = nil self.next_restrictors_update_time = -10000 self.object:set_callback(callback.inventory_info, self.info_callback, self) self.object:set_callback(callback.article_info, self.article_callback, self) self.object:set_callback(callback.on_item_take, self.on_item_take, self) self.object:set_callback(callback.on_item_drop, self.on_item_drop, self) self.object:set_callback(callback.trade_sell_buy_item, self.on_trade, self) -- for game stats --self.object:set_callback(callback.actor_sleep, self.sleep_callback, self) self.object:set_callback(callback.task_state, self.task_callback, self) --self.object:set_callback(callback.map_location_added, self.map_location_added_callback, self) self.object:set_callback(callback.level_border_enter, self.level_border_enter, self) self.object:set_callback(callback.level_border_exit, self.level_border_exit, self) self.object:set_callback(callback.take_item_from_box, self.take_item_from_box, self) --******************************РЕМОНТ***************************************************** self.object:set_callback(callback.use_object, self.repair_start, self)--Установка коллбэка --***************************************************************************************** end --******************************РЕМОНТ***************************************************** function actor_binder:repair_start(obj, who)--Функция коллбека callback.use_object if obj then if obj:section() == "bread" then exp_mod.test_debug() end end end --***************************************************************************************** function actor_binder:net_destroy() if(actor_stats.remove_from_ranking~=nil)then actor_stats.remove_from_ranking(self.object:id()) end -- game_stats.shutdown () db.del_actor(self.object) sr_light.clean_up () self.object:set_callback(callback.inventory_info, nil) self.object:set_callback(callback.article_info, nil) self.object:set_callback(callback.on_item_take, nil) self.object:set_callback(callback.on_item_drop, nil) --self.object:set_callback(callback.actor_sleep, nil) self.object:set_callback(callback.task_state, nil) self.object:set_callback(callback.level_border_enter, nil) self.object:set_callback(callback.level_border_exit, nil) self.object:set_callback(callback.take_item_from_box, nil) --****************************РЕМОНТ********************************** self.object:set_callback(callback.use_object, nil)-- --******************************************************************** if sr_psy_antenna.psy_antenna then sr_psy_antenna.psy_antenna:destroy() sr_psy_antenna.psy_antenna = false end xr_sound.stop_all_sound_object() object_binder.net_destroy(self) end --exp_mod.script--Мой скрипт --Тестовая функция function test_debug()--При использовании "bread" alife():create("bread", vector(),0,0,0) local actor = db.actor local test_obj = actor:object("conserva") --При использовании "bread" нужно удалить два test_obj (если их имеется столько в инвентаре). if test_obj then alife():release(alife():object(test_obj:id()), true) end test_obj = actor:object("conserva") if test_obj then alife():release(alife():object(test_obj:id()), true)--этот код не срабатывает но из игры не выкидывает end end --При вызове этой функции срабатывает только удаление первого test_obj, кроме того повторно эта функция уже не работает. Ссылка на комментарий
Shredder 49 Опубликовано 24 Августа 2015 Поделиться Опубликовано 24 Августа 2015 эта функция alife():release() не удалит клиентский предмет сразу, вызывая actor:object("conserva") второй раз ты получаешь тот же самый предмет и пытаешься его удалить ещё раз. Т.е. тебе нужно пройтись по предметам инвентаря, и удалить "conserva" именно в цикле Ссылка на комментарий
Zander_driver 10 334 Опубликовано 24 Августа 2015 Поделиться Опубликовано 24 Августа 2015 (изменено) @antihumanist, Вот простой тест local id = i[1] local s = alife():object(id) alife():release(s, true) local o = level.object_by_id(id) if o then inv_system.game_message("exist") else inv_system.game_message("not exist") end И знаете какое сообщение выводится? "exist". alife():release() вообще с клиентским объектом ничего не делает, ни сразу ни потом. Она удаляет СЕРВЕРНЫЙ объект. И да, делает это именно сразу. А уже по факту удаления серверного, движок делает так чтобы и клиентский исчез, но произойдет это через некоторое время. а db.actor:object() возвращает клиентский объект. и если вы удалили его серверный аналог, клиентский - в ЭТОТ ЖЕ момент - еще продолжает существовать, вот вам и выдается тот же, который вы пытаетесь удалить повторно. Вообще удобно бывает держать под рукой сформированную таблицу предметов в инвентаре, содержащую среди прочего их id. Изменено 24 Августа 2015 пользователем Zander_driver Мод, где не бывает одинаковых путей - Судьба Зоны. (Лучшее, что у меня получилось на 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. Ссылка на комментарий
Dennis_Chikin 3 658 Опубликовано 24 Августа 2015 Поделиться Опубликовано 24 Августа 2015 вызывая actor:object("conserva") второй раз ты получаешь тот же самый предмет Хуже того, вызывая actor:object() мы получаем какой попало предмет. В зависимости от текущей погоды на марсе (ага, у нас там наверняка еще всякие "перепаковщики", "удалялщики артефактов" и еще черт знает какая ересь, неизвестно что, как и когда делающая). Вообще удобно бывает держать под рукой сформированную таблицу предметов в инвентаре, содержащую среди прочего их id. Угум. Менеджер инвентаря, через который (и только через него) делается ВСЕ. Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Ссылка на комментарий
Grif_on 9 Опубликовано 25 Августа 2015 Поделиться Опубликовано 25 Августа 2015 Приветствую. Подскажите по скрипту. Дело такое: создал в спавне level_changer и хочу до определённого момента его удалить. Написал такую функцию: local lc_id = get_story_object_id("esc_to_marsh_1")if lc_id ~= nil thenalife():release(alife():object(lc_id), true) Вроде всё работает, переход удаляется. Когда нужно вернуть переход, пытаюсь восстановить его через alife():create, но никак не выходит (либо вылет, либо переход не появляется). Подскажите, как правильно прописать alife():create( , чтоб работало как надо? Ссылка на комментарий
Полтергейст 37 Опубликовано 25 Августа 2015 Поделиться Опубликовано 25 Августа 2015 (изменено) Насчёт синтаксиса логики - скоро выложу правленные функции parse_condlist и parse_infop, которые позволят писать вот так {+infop1 =func1} {+infop2 =func2} section1 %+infop3% Это будет восприниматься как если бы вы написали {+infop1 =func1} section1 %+infop3%, {+infop2 =func2} section1 %+infop3% Дополнительно к этому попробую сделать выявление одинаковых и взаимоисключающих условий, а также предотвратить повторный вызов функций в таких ситуациях: {=gulag_inactive(esc_lager)} section1, {!gulag_inactive(esc_lager) +esc_infop1} section2 Изменено 25 Августа 2015 пользователем Полтергейст Ссылка на комментарий
Shredder 49 Опубликовано 25 Августа 2015 Поделиться Опубликовано 25 Августа 2015 @Grif_on, Чтобы заспавнить правильно левел ченджер нужно использовать net-packet, иначе ничего не получится. А действительно ли нужно его удалять? Его же можно просто дизаблить 1 1 Ссылка на комментарий
Overfirst 631 Опубликовано 25 Августа 2015 Поделиться Опубликовано 25 Августа 2015 Чтобы заспавнить правильно левел ченджер нужно использовать net-packet @Grif_on, спавн LC через скрипт: function create_level_changer( p_story_id, -- STORY_ID нового level_changer (понадобится нам позже) p_position, -- вектор, координаты точки, в которой будет располагаться центр нового level_changer p_lvertex_id, -- level_vertext_id - идентифицируют уровень, на котором будет создан level_changer p_gvertex_id, -- game_vertext_id p_dest_lv, -- level_vertex_id - идентифицируют уровень, на который level_changer будет перебрасывать игрока p_dest_gv, -- game_vertex_id p_dest_pos, -- координаты точки, в которой на новом уровне окажется игрок p_dest_dir, -- направрение взгляда игрока p_dest_level, -- название уровня, например "L11_Pripyat" p_silent -- следует задать 1, чтобы подавить вопрос о смене уровня (автоматический переход) ) local obj = alife():create("level_changer", p_position, p_lvertex_id, p_gvertex_id) level.map_add_object_spot(obj.id, "level_changer", "") local packet = net_packet() obj:STATE_Write(packet) -- свойства cse_alife_object local game_vertex_id = packet:r_u16() local cse_alife_object__unk1_f32 = packet:r_float() local cse_alife_object__unk2_u32 = packet:r_u32() local level_vertex_id = packet:r_u32() local object_flags = packet:r_u32() local custom_data = packet:r_stringZ() local story_id = packet:r_u32() local spawn_story_id = packet:r_u32() -- свойства cse_shape local shape_count = packet:r_u8() for i=1,shape_count do local shape_type = packet:r_u8() if shape_type == 0 then -- sphere local center = packet:r_vec3() local radius = packet:r_float() else -- box local axis_x_x = packet:r_float() local axis_x_y = packet:r_float() local axis_x_z = packet:r_float() local axis_y_x = packet:r_float() local axis_y_y = packet:r_float() local axis_y_z = packet:r_float() local axis_z_x = packet:r_float() local axis_z_y = packet:r_float() local axis_z_z = packet:r_float() local offset_x = packet:r_float() local offset_y = packet:r_float() local offset_z = packet:r_float() end end -- свойства cse_alife_space_restrictor local restrictor_type = packet:r_u8() -- свойства cse_level_changer local dest_game_vertex_id = packet:r_u16() local dest_level_vertex_id = packet:r_u32() local dest_position = packet:r_vec3() local dest_direction = packet:r_vec3() local dest_level_name = packet:r_stringZ() local dest_graph_point = packet:r_stringZ() local silent_mode = packet:r_u8() packet:w_begin(game_vertex_id) -- game_vertex_id packet:w_float(cse_alife_object__unk1_f32) packet:w_u32(cse_alife_object__unk2_u32) packet:w_u32(level_vertex_id) -- level_vertex_id packet:w_u32( bit_not(193) ) -- object_flags = -193 = 0xFFFFFF3E packet:w_stringZ(custom_data) packet:w_u32(p_story_id) -- story_id packet:w_u32(spawn_story_id) packet:w_u8(1) -- количество фигур -- packet:w_u8(0) -- тип фигуры: сфера -- packet:w_vec3(vector():set(0, 0, 0)) -- sphere_center -- packet:w_float(3.0) packet:w_u8(1) -- тип фигуры: box packet:w_float(2) -- axis_x_x packet:w_float(0) -- axis_x_y packet:w_float(0) -- axis_x_z packet:w_float(0) -- axis_y_x packet:w_float(4) -- axis_y_y packet:w_float(0) -- axis_y_z packet:w_float(0) -- axis_z_x packet:w_float(0) -- axis_z_y packet:w_float(4) -- axis_z_z packet:w_float(0) -- offset_x packet:w_float(0) -- offset_y packet:w_float(0) -- offset_z packet:w_u8(3) -- restrictor_type packet:w_u16(p_dest_gv) -- destination game_vertex_id packet:w_s32(p_dest_lv) -- destination level_vertex_id packet:w_vec3(p_dest_pos) -- destination position packet:w_vec3(p_dest_dir) -- destination direction (направление взгляда) packet:w_stringZ(p_dest_level) -- destination level name packet:w_stringZ("start_actor_02") -- some string, always const packet:w_u8(p_silent) -- 1 for silent level changing packet:r_seek(0) obj:STATE_Read(packet, packet:w_tell()) news_manager.send_tip(db.actor, "Новый путь", nil, nil, 10000) end --Сам спавн function lc() if (not has_alife_info("blablabla" )) then script_name.create_level_changer(11111, vector():set(82.091148376465, 24.181016921997, -22.771390914917), 432354, 3119, 2349, 158301, vector():set(369.19384765625, -0.00164741277694702, -172.899780273438), vector():set( 0.0,0.0,0.0 ),"L12_Stancia",0) db.actor:give_info_portion("blablabla") end end 1 Ранее был известен под ником BoBaH_671. Ссылка на комментарий
Dennis_Chikin 3 658 Опубликовано 25 Августа 2015 Поделиться Опубликовано 25 Августа 2015 {+infop1 =func1} {+infop2 =func2} section1 %+infop3% Так почему бы сразу не сделать уже function = condition и section = condition ? Или вообще [section] condition1 = condition2 = ... action1 = action2 = ... Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Ссылка на комментарий
Полтергейст 37 Опубликовано 25 Августа 2015 Поделиться Опубликовано 25 Августа 2015 (изменено) Dennis_Chikin Так почему бы сразу не сделать уже function = condition и section = condition ? Или вообще Во-первых - надо оставлять совместимость. Никто не будет переписывать всё ранее наработанное только потому, что какой-то другой синтаксис лучше. Во-вторых, если так сделать, тогда будет дублирование условий. Оно и в существующем варианте есть (это то, от чего я в своём варианте избавляюсь), но так его ещё больше будет. Теперь надо будет условия писать для КАЖДОГО action отдельно, и конструкция {+info} section2 %=action4 +info2% разрастётся до [section1] section2 = info action4 = info info2 = infoи это ещё один из самых "безобидных" примеров. В-третьих, синтаксис самих ini-файлов (деление на секции и строки) накладывает свои ограничения. Чем компактнее запись, и чем лучше она умещается в одну строку без дублирования - тем лучше. Изменено 25 Августа 2015 пользователем Полтергейст 1 Ссылка на комментарий
abramcumner 1 157 Опубликовано 25 Августа 2015 Поделиться Опубликовано 25 Августа 2015 В дублирование нет ничего плохого. Зато есть четкая форма записи: условие, секция, действие. Сейчас у тебя будет несколько условий - придется разбирать ДНФ или строить ее при написании. От дублирования условий всегда можно избавиться написав функцию, в которой проверить инфопорции, другие функции как только захочешь. {=gulag_inactive(esc_lager)} section1, {!gulag_inactive(esc_lager) +esc_infop1} section2Конкретно здесь вторая проверка !gulag_inactive лишняя - она точно истина, иначе ушли бы на секцию section1 1 Ссылка на комментарий
_Val_ 2 225 Опубликовано 25 Августа 2015 Поделиться Опубликовано 25 Августа 2015 Зато есть четкая форма записи И до кучи - наглядно. Ссылка на комментарий
Полтергейст 37 Опубликовано 25 Августа 2015 Поделиться Опубликовано 25 Августа 2015 (изменено) abramcumner В дублирование нет ничего плохого. Зато есть четкая форма записи: условие, секция, действие.В чём выражается "нечёткость" однострочной формы записи? Это обычное if-then-elseif-else, просто записанное с использованием спец. символов - скобок, процентов, двоеточий и +-=. То, что реализация её разбора кривовата - это уже проблемы этой реализации, а не самой формы записи. И кстати, если писать всё в виде action1 = condition1 - всё равно спецсимволы никуда не денутся. Может их будет чуть меньше, но не намного.От дублирования условий всегда можно избавиться написав функцию, в которой проверить инфопорцииНу и что, не одно - так другое. Намного проще избавиться от дублирования, один раз подправив реализацию разбора condlist'ов, чем по сто раз писать костыли, которые будут обходить её недостатки. Конкретно здесь вторая проверка !gulag_inactive лишняя - она точно истина, иначе ушли бы на секцию section1Ну тогда так: {=gulag_inactive(esc_lager) -esc_infop1} section1, {=gulag_inactive(esc_lager) +esc_infop1} section2 Изменено 25 Августа 2015 пользователем Полтергейст Ссылка на комментарий
_Val_ 2 225 Опубликовано 25 Августа 2015 Поделиться Опубликовано 25 Августа 2015 (изменено) В чём выражается "нечёткость" Вот это стремно выглядит... {+infop1 =func1} {+infop2 =func2} Так и хочется подумать - а чего тут не хватает? Изменено 25 Августа 2015 пользователем _Val_ 1 Ссылка на комментарий
abramcumner 1 157 Опубликовано 25 Августа 2015 Поделиться Опубликовано 25 Августа 2015 (изменено) Как программисту мне твоё нововведение нравится: условия в фигурных скобочках объединяются по "and", фигурные скобочки между собой по "or". Правильно я понял? Как пользователю, который пишет и читает логику, не нравится. Нечеткость не однострочной формы, а то что фигурных скобочек станет несколько - непонятно, то ли пропустили секцию, то ли так и хотели. Разбирать условия станет сложнее. С условиями в логике есть вполне определенные сложности. Как доказательство подойдет то, что ты не "упростил" gulag_inactive. Исходный пример: {=gulag_inactive(esc_lager)} section1, {!gulag_inactive(esc_lager) +esc_infop1} section2Программистский вариант: {=gulag_inactive(esc_lager)} section1, {+esc_infop1} section2человеческий(мне программисткий ближе ) вариант: {=gulag_inactive(esc_lager)} section1, {=gulag_active(esc_lager) +esc_infop1} section2или так: {!gulag_active(esc_lager)} section1, {=gulag_active(esc_lager) +esc_infop1} section2Убрать двойное отрицание, чтобы мозг не ломать на пустом месте и в каждом переключении указывать полные условия. С предотвращением повторного вызова полностью согласен. Вроде не сложно делается - завести таблицу {[токен] = |ложь, истина, нил|} За значением токена лезть в таблицу, если "нил" - вычислить. Изменено 25 Августа 2015 пользователем abramcumner Ссылка на комментарий
_Val_ 2 225 Опубликовано 25 Августа 2015 Поделиться Опубликовано 25 Августа 2015 Программистский вариант - неправильный по сути, ибо в обоих случаях должно проверяться gulag_active(esc_lager), а у тебя переход во вторую секцию чисто по поршню. Ссылка на комментарий
Kirgudu 1 217 Опубликовано 25 Августа 2015 Поделиться Опубликовано 25 Августа 2015 (изменено) @_Val_, это не так, поскольку при оригинальном разборе проверка второго условия происходит только если первое не сработало. А значит, неявным образом учитывается результат проверки первого условия. Как программисту мне твоё нововведение нравится: условия в фигурных скобочках объединяются по "and", фигурные скобочки между собой по "or". Правильно я понял? Как пользователю, который пишет и читает логику, не нравится. Нечеткость не однострочной формы, а то что фигурных скобочек станет несколько - непонятно, то ли пропустили секцию, то ли так и хотели.Можно для «or» использовать не пробел, а ввести дополнительный разделитель (чтобы было проще читать - вообще неиспользуемый в логике в настоящее время символ, можно с опциональными пробелами вокруг него), который однозначно будет указывать на новый тип конструкции. Те пользователи, которые привыкли писать по-старому и не хотят разбираться с новыми возможностями (как вариант - вообще не в курсе этих возможностей), так и продолжат писать по-старому. А кто захочет - будет использовать, наперёд зная, что означает данное написание. Изменено 25 Августа 2015 пользователем Kirgudu 2 Инструмент Ссылка на комментарий
abramcumner 1 157 Опубликовано 25 Августа 2015 Поделиться Опубликовано 25 Августа 2015 @_Val_, нет. Сначала проверяется первое условие: неактивный гулаг. Если он неактивен уходим на секцию1. Если активен, проверяем дальше. Соответственно проверять второй раз активность смысла нет - он же точно активен. Ссылка на комментарий
Полтергейст 37 Опубликовано 25 Августа 2015 Поделиться Опубликовано 25 Августа 2015 (изменено) abramcumner Правильно я понял?Да. Нечеткость не однострочной формы, а то что фигурных скобочек станет несколько - непонятно, то ли пропустили секцию, то ли так и хотели. Разбирать условия станет сложнее.Оно-то так, только сделать с этим вряд ли что-то можно. Оставлять как есть - значит дублировать условия или писать костыли. Менять на мой вариант - не всем понятно будет. Делать что-то совсем иное - будет проблемы с совместимостью. Остаётся только вводить новые спецсимволы для группировки действий, но почти все и так уже заняты, а именно ({},@%=!~:|). Можно попробовать ввести #, $, *, & или ?. & и * по понятным причинам лучше не использовать. Из оставшихся больше подходит ?. Вот как-то так это будет выглядеть: {+info1} ? {+info2} section_new Но опять же, может быть что-то непонятно тем, кто пишет логику - новый вариант будет непривычен, а также начнутся проблемы с копипастой новых конструкций в моды со старыми скриптами. Изменено 25 Августа 2015 пользователем Полтергейст Ссылка на комментарий
Рекомендуемые сообщения
Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий
Комментарии могут оставлять только зарегистрированные пользователи
Создать аккаунт
Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!
Зарегистрировать новый аккаунтВойти
Есть аккаунт? Войти.
Войти