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

Скриптование


Svoboда

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

kratos888.

1. Функцию то ты используешь, но по всей видимости не до конца понимаешь как она работает. Чтобы story_id читался, нужно перевести НПС оффлайн и обратно, либо сейв-лоад.

 

Поделиться этим сообщением


Ссылка на сообщение

Такой вопрос: как работает класс profile_timer? Считает ли он время выполнения посторонней функции при вызове её из измеряемого участка кода? Например:

local timer = profile_timer()
timer:start()
-- здесь код...
-- здесь вызов функции
-- здесь опять код...
timer:stop()

Будет ли учтено время работы вызываемой функции?

Поделиться этим сообщением


Ссылка на сообщение

Ну и я свою "ляпту" внесу. :)

--# Таблица предметов, которые нужно раздобыть и в последствии отдать.
local need_item = {"bread",8,"kolbasa",6,"conserva",10}

--# Функция принимает в качестве аргумента таблицу вида:
--# {"section_name", count, "section_name", count, ...}
function predmety_yazhik_complete (p)
  local actor = db.actor
  --# Разобъём аргумент (таблицу) на пары, где twain - это секция предмета, который проверяем, а twain+1 - его количество.
  for twain = 1, #p, 2 do
     --# Для каждой пары секция - количество заведём один счётчик, который будет считать количесвто предметов в инвенторе.
     local cnt = 0
     --# Перебираем инвентарь ГГ.
     actor:iterate_inventory(
	 function (dummy, item)
	 --# Если секция совпала, то увеличим сумму.
	 if item:section() == p[twain] then cnt = cnt + 1 end
	 end, nil)
     --# Если общая сумма указанного предмета меньше нужной, т.е. не хватает, то заканчиваем счёт и возвращаем соответствующее значение.
     if cnt < p[twain+1] then return false end
  end
  --# Если все предметы есть в указанном количестве - вернём true.
  return true
end

Вернёт true если в инвентаре присутствует указанное количество указанных предметов.

 

 

P.S. И правда, ребята, прячьте код под спойлер. В шапке об этом ведь написано.

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

Поделиться этим сообщением


Ссылка на сообщение

Viнt@rь

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

 

По сути, метод add_call пространства имён level есть колбек аргументами которого являются две функции.

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

Вообще метод перегруженный. Можешь глянуть в lua_help.script и в справочнике было какое-то описание этому.

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

Поделиться этим сообщением


Ссылка на сообщение

serega-gamer, причину тебе уже назвали. Но хотелось бы ещё добавить, что не очень то у тебя код оптимизированный получился. Может лучше так!?

local function check_condition (item_in_slot)
  return item_in_slot:condition() < 1 and item_in_slot:condition() >= 0.2
end
function repair_wpn_1()
  local item_in_slot = db.actor:item_in_slot(2)
  local act_rank = ranks.get_obj_rank_name(db.actor)
  local cond_standard = {
	 ["novice"]    = (item_in_slot:condition() + (math.random(20)+20)/100),
	 ["experienced"]    = (item_in_slot:condition() + (math.random(20)+30)/100),
    ["veteran"]    = (item_in_slot:condition() + (math.random(20)+40)/100),
    ["master"]    = (item_in_slot:condition() + (math.random(20)+50)/100),
  }
  for i = 0, db.actor:object_count() - 1 do
  local item = db.actor:object(i)
  if item:id() ~= item_in_slot:id() and item:section() == item_in_slot:section() then
	 if check_condition (item_in_slot) then
	    item_in_slot:set_condition(cond_standard[act_rank])
	    this.repair_wpn_sound()
	    alife():release(alife():object(item:id()), true)
	    return
	 end
  end
  end
end

 

Поделиться этим сообщением


Ссылка на сообщение

Dennis_Chikin, объектом к которому "прикручен" биндер. Нет, вызываются методы конечно движком, но, так сказать, виновник этого - объект. В общем вот здесь всё весьма подробно расписано: >>ClicK Me<<.

Поделиться этим сообщением


Ссылка на сообщение

proper70

И еще: в файле gulag_escape.script я нашел такую строку (правда, она закомментена):

-- online = true,

а что будет, если ее раскомментить?

Этот параметр, в некотором смысле, аналогичен секции spawner в custom_data. Т.е. если стоят условия, то он определяет параметры выхода в онлайн, если же поставить true, то любой НПС будучи на данной работе всегда будет находиться в онлайне.

В целом информация очень интересная. От меня лично - благодарю.

Поделиться этим сообщением


Ссылка на сообщение

proger_Dencheek, интересно, чем же твоя функция лучше? Парой дополнительных проверок и возможностью указывать количество предметов для передачи? Боюсь, что в данном случае "твоя" функция так же не поможет...

 

 

riddik121, вероятнее всего ты не правильно передаешь в функцию "кто-есть-кто". Вызывая на реплике НПС, ты передаёшь предмет от актора к актору. Попробуй вызвать функцию так:

function anarhist_pkm_done(first_speaker, second_speaker)
  dialogs.relocate_item_section(first_speaker, "wpn_pkm", "out")
end

 

Что касается функции по универсальнее, то позволь тебе предложить следующее:

--# Функция трансфера предметов в указанном количестве.
--# Избавился от необходимости вставлять квестовый предмет в таблицу quest_section.
--# Теперь "квестовость" предмета определяется по наличию поля quest_item, со значением true, в секции предмета.
--# victim - ['userdata'] от кого (type == "in") либо кому (type == "out") передавать предмет;
--# section - ['string']  секция передаваемого предмета;
--# type - ['string']  тип передачи ("in" - актору, "out" - от актора);
--# count - ['number']  количество предметов для передачи (по умолчанию - 1);
--# hide - ['boolean']  показывать ли факт передачи в виде сообщения в окне диалога (true - скрыть).
function relocate_item_section (victim, section, type, count, hide)
  local actor = db.actor
  local ini = system_ini()
  --# Определим является ли передаваемый предмет квестовым.
  local item_is_quest = ini:section_exist(section) and ini:line_exist(section, "quest_item") and ini:r_bool(section, "quest_item")
  if actor and victim then
   --# Передвать нужно от НПС актору.
   if type == "in" then
   --# Если предмет квестовый, то ...
   if item_is_quest then
    --# Передадим предмет(ы).
    transfer_item_between_npc (victim, actor, section, count)
   --# Иначе просто заспавним в нужном количестве.
   else
    spawn_to_inventory (section, actor, count)
   end
   --# Передавать нужно от актора НПСу.
   elseif type == "out" then
   --# Передадим их НПС.
   transfer_item_between_npc (actor, victim, section, count)
   end
   --# Нужно ли явно сообщать о передачи в окне диалога?
   if not hide then
   news_manager.relocate_item(actor, type, section)
   end
  end
end
--# Функция спавна предметов в инвентарь.
--# section - ['string']  секция предмета, который будем спавнить;
--# whom - ['userdata'] кому будем спавнить (по умолчанию актору);
--# count - ['number']  сколько будем спавнить (по умолчанию 1).
--# Если каким-то образом section равен nil/false, либо предмет не является инвентарным, спавн происходить не будет.
function spawn_to_inventory (section, whom, count)
  --# Проверим передана ли секция, и предмет инвентарный.
  if not section or not system_ini():line_exist(section, "inv_name") then
   return
  end
  --# Определим кому спавнить, если whom не равен 'userdata', то спавнить будем в инвентарь актора.
  local actor = type(whom) == "userdata" and whom or db.actor
  --# Спавним в указанном количестве, либо в одном экземпляре, если count не передан.
  for i=1, count or 1 do
   alife():create(section, actor:position(), actor:level_vertex_id(), actor:game_vertex_id(), actor:id())
  end
end
--# Функция передачи предметов от одного НПС к другому в указанном количестве.
--# who - ['userdata'] кто передаёт;
--# whom - ['userdata'] кому передавать;
--# section - ['string']  секция предмета;
--# count - ['number']  количество предметов (если не указано, то 1).
function transfer_item_between_npc (who, whom, section, count)
  --# Если нет от кого и кому передавать, то выйдем.
  if not who and not whom then
   return
  end
  --# Передадим указанное количество предметов, если не передан count, то передадим один предмет.
  for i = 1, count or 1 do
   who:transfer_item(who:object(section), whom)
  end
end

 

  • Нравится 3

Поделиться этим сообщением


Ссылка на сообщение

riddik121, это зависит от того, кто говорит фразу, в которой вызвана функция. Вообще первым аргументом передаётся говорящий, вторым - оппонент.

Поделиться этим сообщением


Ссылка на сообщение

proger_Dencheek, а когда это родная функция требовала "объявления first_speaker, second_speaker"? И у просившего проблемы как раз не с аргументами, а с определением того, на кокой реплике вызывать функцию, либо кого именно передавать в неё.

P.S. Постарайся в следующий раз давать конкретный ответ на вопрос, а не распространять копи-паст. На этом оффтоп окончен.

Поделиться этим сообщением


Ссылка на сообщение

Desertir, если уж на то пошло, то в Lua нет классов, в Lua есть таблицы с помощью которых эмулируется ООП, причём заметьте - весьма удачно. Самый банальный пример, который не излагает всей сути объектного программирования, но показывает суть...

Car = {_model = "", _year = 0, _type = ""}

function Car:setData (model, year, type)
self._model = model
self._year = year
self._type = type
end
function Car:getData ()
print (self._model.."; "..self._year.."; "..self._type)
end

local Tarantayka = Car
Tarantayka:setData("ZAZ", 1970, "SUV")
Tarantayka:getData()

Подправил... Вот так будет нагляднее.

 

Вот здесь: >>ClicK Me<<, на пятой странице, весьма доступно описан этот момент.

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

Поделиться этим сообщением


Ссылка на сообщение

Другого ООП в Lua нет, всё реализуется посредством таблиц.

Перейди по ссылке, что я дал, там есть все ответы на твои вопросы.

Поделиться этим сообщением


Ссылка на сообщение

Это не то, чтобы "полезный" вариант, это единственный вариант реализации ООП в Lua.

Что касается сабжа - неужто те, классы, которые реализуют различные менеджеры, так "тормозят"? Время их работы никчёмно, и разница в десять раз на одном миллионе итераций смотрится просто жалко, к тому же класс profile_timer считает время МИКРОсекундах, получается приблизительно полсекунды на весь процесс - это также не делает из этого бесполезной тратой времени и ресурсов. ИМХО, овчинка выделки не стоит.

Поделиться этим сообщением


Ссылка на сообщение

Даже если и возникнет желание, давайте его обсуждать не здесь, создайте по соседству тему, кто желает, будем обсуждать там, а то мы и так здесь нафилософствовали...

Далее, пожалуйста, по существу: конкретный вопрос - конкретный ответ.

Поделиться этим сообщением


Ссылка на сообщение

Shredder, а вот с оптимизацией примера логики проколочка... Это только затормозит работу. :)

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

Хотя где-где, а в логике есть что оптимизировать, например если взглянуть на функцию cfg_get_switch_conditions в файле xr_logic.script, то можно прийти к не до умению с вопросом: почему именно так?

Поделиться этим сообщением


Ссылка на сообщение

Shredder, после этой функции будет вызвана ещё одна - pick_section_from_condlist, которая будет проверять эти самые условия и перебирать она будет все элементы, именно вот здесь, проверка единственного значения в таблице будет быстрее проверки из четырёх, ко всему в последствии, в саму функцию check_npc_name, передадутся четыре параметра, где вновь будет идти их перебор.

ИМХО, как сказал Саша, всё это настолько мелочно, что бороться за производительность, жертвуя читабельностью кода, - глупо. Одна загрузка модели с анимациями займёт больше времени, чем 1М итераций с инициализацией переменной. Скорее, нужно просто сделать по "человечески" чтобы код был понятнее и глядя на него становилось ясно, что он делает, плюс по возможности использовать какие-то техники оптимизации кода, что тоже будет не плохо. Одним словом - нужно искать компромисс.

 

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

--# Табличка соответствия что - чем парсить.
local tbl_condition = {
   ["on_actor_dist_le"] = cfg_get_number_and_condlist,
   ["on_actor_dist_le_nvis"] = cfg_get_number_and_condlist,
   ["on_actor_dist_ge"] = cfg_get_number_and_condlist,
   ["on_actor_dist_ge_nvis"] = cfg_get_number_and_condlist,
   ["on_timer"] = cfg_get_number_and_condlist,
   ["on_game_timer"] = cfg_get_number_and_condlist,
   ["on_signal"] = cfg_get_string_and_condlist,
   ["on_actor_in_zone"] = cfg_get_string_and_condlist,
   ["on_actor_not_in_zone"] = cfg_get_string_and_condlist,
   ["on_info"] = cfg_get_condlist,
   ["on_actor_inside"] = cfg_get_condlist,
   ["on_actor_outside"] = cfg_get_condlist,
   ["on_npc_in_zone"] = cfg_get_npc_and_zone,
   ["on_npc_not_in_zone"] = cfg_get_npc_and_zone
   }
function cfg_get_switch_conditions (ini, section, npc)
  --# Табличка будет хранить парсеные условия.
  local parse_tbl = {}
  --# Индекс условия в табличке parse_tbl.
  local num = 1
  --# Разберём таблицу соответствий tbl_condition.
  for field, func in pairs(tbl_condition) do
  --# Здесь:
  --# field - поле, которое будем парсить;
  --# func - имя функции, которой будем парсить.
   --# Проверка того, что выбранный параметр существует в нашей секции.
   --# По сути нужна для оптимизации, чтобы не обрабатываеть лишнее.
   if section and ini:section_exist(section) and ini:line_exist(section, field) then
   --# Порядковый номер одноимённых условий.
   local i = 1
   --# Распарсим поле field при помощи соответствующей функции func.
   local cond = func(ini, section, field, npc)
   --# Пока таблица cond существует, т.е. указанное поле парсится, будем вносить услвоия в таблицу parse_tbl.
   while cond ~= nil do
    --# Вносим условие в таблицу.
    parse_tbl[num] = cond
    --# Увеличиваем индекс.
    num = num + 1
    --# Проверим есть ли одноимённые условия?
    cond = func(ini, section, field..i, npc)
    --# Посмотрим есть ли ещё одноимённые условия, вдруг их больше одного!?
    i = i + 1
   end
   end
  end
  --# Возвращаем распарсенные услвоия в виде таблицы.
  return parse_tbl
end

 

Поделиться этим сообщением


Ссылка на сообщение

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

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

Поделиться этим сообщением


Ссылка на сообщение

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

Поделиться этим сообщением


Ссылка на сообщение

*Shoker*, если не секрет конечно, по средством какого метода ты пытаешься развернуть объект при спавне?

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

Поделиться этим сообщением


Ссылка на сообщение

Wookie, для класса io существует метод lines, принимающий в качестве аргумента имя файла, и возвращает функцию итератор, которая при вызове возвращает по одной строку из указанного файла, как только достигнет конца файла - вернёт nil, при этом файл будет закрыт.
Точно не помню, но кажется можно вызывать и без аргумента, в таком случае будет обрабатываться стандартный поток ввода, по окончании итерации ничего закрываться не будет.

for line in io.lines("filenNme") do ... end

Это работает на чистом Lua, но и на ЗП должно работать.

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

Поделиться этим сообщением


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

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