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

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

Ужасно. Неизвестно что делается неизвестно когда с неизвестно чем.

 

Ну и что хотим получить в результате ?

Еще раз подумать над вот этим вот вопросом, а потом уже думать, как это сделать.

 

Очевидно, что "есть" ничего не надо совсем. Ну и темку про использование предметов почитать.

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

Ужасно. Неизвестно что делается неизвестно когда с неизвестно чем.

Вот переделал все для демонстрации бага на стандартных вещах и без "лишних" функций.

Вызов бага показан в функции 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, кроме того повторно эта функция уже не работает.

 

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

эта функция alife():release() не удалит клиентский предмет сразу, вызывая actor:object("conserva") второй раз ты получаешь тот же самый предмет и пытаешься его удалить ещё раз. Т.е. тебе нужно пройтись по предметам инвентаря, и удалить "conserva" именно в цикле

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

@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.

Изменено пользователем 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.

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

вызывая actor:object("conserva") второй раз ты получаешь тот же самый предмет

Хуже того, вызывая actor:object() мы получаем какой попало предмет. В зависимости от текущей погоды на марсе (ага, у нас там наверняка еще всякие "перепаковщики", "удалялщики артефактов" и еще черт знает какая ересь, неизвестно что, как и когда делающая).

Вообще удобно бывает держать под рукой сформированную таблицу предметов в инвентаре, содержащую среди прочего их id.

Угум. Менеджер инвентаря, через который (и только через него) делается ВСЕ.

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

Приветствую. Подскажите по скрипту. Дело такое: создал в спавне level_changer и хочу до определённого момента его удалить. Написал такую функцию:

local lc_id = get_story_object_id("esc_to_marsh_1")
if lc_id ~= nil then
alife():release(alife():object(lc_id), true)

Вроде всё работает, переход удаляется. Когда нужно вернуть переход, пытаюсь восстановить его через alife():create, но никак не выходит (либо вылет, либо переход не появляется). Подскажите, как правильно прописать alife():create( , чтоб работало как надо?
 

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

Насчёт синтаксиса логики - скоро выложу правленные функции 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
Изменено пользователем Полтергейст
Ссылка на комментарий

@Grif_on, Чтобы заспавнить правильно левел ченджер нужно использовать net-packet, иначе ничего не получится.

А действительно ли нужно его удалять? Его же можно просто дизаблить

  • Спасибо 1
  • Согласен 1
Ссылка на комментарий

 

 

Чтобы заспавнить правильно левел ченджер нужно использовать 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.

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

{+infop1 =func1} {+infop2 =func2} section1 %+infop3%

Так почему бы сразу не сделать уже function = condition и section = condition ?

Или вообще

[section]

condition1 =

condition2 =

...

action1 =

action2 =

...

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

Dennis_Chikin

Так почему бы сразу не сделать уже function = condition и section = condition ?

Или вообще

Во-первых - надо оставлять совместимость. Никто не будет переписывать всё ранее наработанное только потому, что какой-то другой синтаксис лучше. Во-вторых, если так сделать, тогда будет дублирование условий. Оно и в существующем варианте есть (это то, от чего я в своём варианте избавляюсь), но так его ещё больше будет. Теперь надо будет условия писать для КАЖДОГО action отдельно, и конструкция {+info} section2 %=action4 +info2% разрастётся до

[section1]
section2 = info
action4 = info
info2 = info
и это ещё один из самых "безобидных" примеров.

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

Изменено пользователем Полтергейст
  • Нравится 1
Ссылка на комментарий

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

Сейчас у тебя будет несколько условий - придется разбирать ДНФ или строить ее при написании.

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

 

{=gulag_inactive(esc_lager)} section1, {!gulag_inactive(esc_lager) +esc_infop1} section2
Конкретно здесь вторая проверка !gulag_inactive лишняя - она точно истина, иначе ушли бы на секцию section1
  • Согласен 1
Ссылка на комментарий

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
Изменено пользователем Полтергейст
Ссылка на комментарий
В чём выражается "нечёткость"

Вот это стремно выглядит...

{+infop1 =func1} {+infop2 =func2}

Так и хочется подумать - а чего тут не хватает?

Изменено пользователем _Val_
  • Согласен 1
Ссылка на комментарий

Как программисту мне твоё нововведение нравится: условия в фигурных скобочках объединяются по "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
Убрать двойное отрицание, чтобы мозг не ломать на пустом месте и в каждом переключении указывать полные условия.

 

С предотвращением повторного вызова полностью согласен. Вроде не сложно делается - завести таблицу {[токен] = |ложь, истина, нил|}

За значением токена лезть в таблицу, если "нил" - вычислить.

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

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

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

@_Val_, это не так, поскольку при оригинальном разборе проверка второго условия происходит только если первое не сработало. А значит, неявным образом учитывается результат проверки первого условия. 

 

Как программисту мне твоё нововведение нравится: условия в фигурных скобочках объединяются по "and", фигурные скобочки между собой по "or". Правильно я понял? Как пользователю, который пишет и читает логику, не нравится. Нечеткость не однострочной формы, а то что фигурных скобочек станет несколько - непонятно, то ли пропустили секцию, то ли так и хотели.

Можно для «or» использовать не пробел, а ввести дополнительный разделитель (чтобы было проще читать - вообще неиспользуемый в логике в настоящее время символ, можно с опциональными пробелами вокруг него), который однозначно будет указывать на новый тип конструкции.

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

Изменено пользователем Kirgudu
  • Согласен 2
Ссылка на комментарий
@_Val_, нет. Сначала проверяется первое условие: неактивный гулаг. Если он неактивен уходим на секцию1. Если активен, проверяем дальше. Соответственно проверять второй раз активность смысла нет - он же точно активен.
Ссылка на комментарий

abramcumner

Правильно я понял?

Да.

 

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

Оно-то так, только сделать с этим вряд ли что-то можно. Оставлять как есть - значит дублировать условия или писать костыли. Менять на мой вариант - не всем понятно будет. Делать что-то совсем иное - будет проблемы с совместимостью. Остаётся только вводить новые спецсимволы для группировки действий, но почти все и так уже заняты, а именно ({},@%=!~:|). Можно попробовать ввести #, $, *, & или ?. & и * по понятным причинам лучше не использовать. Из оставшихся больше подходит ?.

 

Вот как-то так это будет выглядеть:

{+info1} ? {+info2} section_new

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

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

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

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

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

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

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

Войти

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

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

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