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

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

Как получить доступ к полям таблицы вида:

 

local tbl1 = { tbl2 = { tbl3 = {"section"}}}

 

Циклами делать не хочется, делаю вот так

 

local section = tbl1[tbl2]["tbl3"][[tbl2]["tbl3"][1]]

но вылетает.

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

Struck, научись, плз, задавать вопросы, о чем уже писалось тебе.

Во-первых, если вылетает - то и приводи строки лога о вылете.

Во-вторых, данный топик по скриптам, т.е. по сценариям, а не по общим вопросам использования Lua.

Для подобных вопросов имеется топик "Язык Lua. Общие вопросы программирования."

Ну и ... не стОит пытаться бездумно употреблять символы, надеясь что получиться рабочий код. Почитай основы / мануалы по Lua, лишним не будет.

Подсказка: local section = tbl1.tbl2.tbl3[1]

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

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

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

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

Или если его нету, то есть ли способ вывести поверх инвентаря текст?

Зарание спасибо. :)

Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О

Мастер аномалий на свою заднюю точку.

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

В Xray - Extension такая возможность имеется: GUIListBox():GetMainInputReceiver(), только окно, возвращаемое этой функцией доступно на следующем апдейте.

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

Все доброго дня!

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

Т.е по такому типу:

 

local check_list = {
[1] = { i = {"item1", "item2"}},
[2] = { i = {"item3", "item4"}},
.......
}

function check(p)
 local list = check_list[p]
    for _, v in pairs (list.i) do
      local item = db.actor:object(v)
          if item then
          ...
          end
     end
end

Однако проверяется только 1 предмет - item1. Чувствую, что нужно "грызть" for _, v in pairs (list.i) do, однако мозгов не хватает.

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

Я бы так сделал:


function check(p)
local list = check_list[p]
local founded = 0
for k,v in ipairs (list.i) do
local item = db.actor:object(v)
if item then
founded = founded + 1
end
end
return founded == #list.i
end

 

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

Shredder, не совсем то получилось. Попробую объяснить подробнее:

Если у актора есть 2 итема в рюкзаке (по первому полю таблицы), то совершаем какое то действие.

Для проверки, поставил вызов на постоянный апдейт и добавил выдачу СМС при условии, что все ок.

Что имеем: спавним 1 итем - сразу приходит СМС. Убираем его и спавним 2 итем - СМС приходит.

Спавним 1 и 2 итем, СМС есть. Выкидываем 1 или 2 итем - СМС есть. Выкидываем все итемы - СМС нету. Подбираем 1 любой итем - СМС

есть.

Т.е если в рюкзаке есть какой то любой из этих 2 итемов - тогда действие.

////////////////////////////

А нужно так: если мы имеем в рюкзаке именно 2 итема (а не 1 какой то из них), то только тогда действие.

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

Как вариант:

 

local check_list = {
[1] = { i = {"item1", "item2"}},
[2] = { i = {"item3", "item4"}},
.......
}

function check(p)
local list = check_list[p]
local valid = true

	 for _, v in pairs (list.i) do
	 local item = db.actor:object(v)
	  if item == nil then --> Не нашли предмета в инвентаре
		 valid = false --> ставим флажок в false
		 break --> останавливаем цикл
	  end
	 end

	 if valid then --> если флажок true, то значит оба предмета есть в инвентаре
	 --\\ тут вызываешь свою функцию
	 end
end

 

А в твоём коде ошибка в "if item then"

У тебя условие будет выполняться столько раз, сколько предметов из списка у тебя есть в инвентаре, ведь цикл найдя 1 предмет пошлёт тебе СМС, и пойдёт дальше выполняться, а там если найдёт 2 предмет, то снова пошлёт тебе СМС.

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

Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О

Мастер аномалий на свою заднюю точку.

Ссылка на комментарий
local tbl = {
["ammo_9x18_ap"] = 3,
["wpn_pm"] = 2
}
check_items(tbl)

function check_items(t)
db.actor:iterate_inventory(
function (dummy, oItem)
if t[oItem:section()] and t[oItem:section()]~=0 then
t[oItem:section()] = t[oItem:section()]-1
end
end
,nil)

for k,v in pairs(t) do
if v!=0 then return false end
end

return true
end

Freedom

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

Напоминание: для портянок кодов используем спойлеры!

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

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

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

--# Таблица предметов, которые нужно раздобыть и в последствии отдать.
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
Ссылка на комментарий

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

 

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

Многие параметры задаются в конфиг-файлах (*.ltx), в которых вполне обычной выглядит запись типа:

[items]
need_item = bread, 8, kolbasa, 6, conserva, 10

- которую проще считать именно в табличку 1-го вида, а не 2-го, и далее уже распарсить готовыми 'штатными' функциями.

 

Этот же формат встречается и в 'штатной' логике или all.spawn'е (те же респавнеры, к примеру), где параметры различного типа передаются именно списком...

 

Т.о. что удобнее и на каком этапе - зависит и от исходных данных (их формата), и от контекста задачи и конечно же от субъективных предпочтений.

 

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

Во-первых, в таком виде данные в таблице хранятся как обычный массив - а это:

1. Меньше памяти выделяется для её инициализации.

2. Lua порядком быстрее работает с массивами, нежели с хеш-таблицами.

Во-вторых, как уже сказали, это моё субъективное предпочтение - я поделился им. :)

ColR_iT

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

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

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

В сендбоксе от xStream, в скрипте xs_sandbox и в системе таймеров(слотов/сигналов) от Malandrinus в скрипте ogse_signals заприметил очень интересную строчку(заприметил то давно, но сильный интерес она вызвала сейчас) - level.add_call(hanged_calls_check, function()end), как и когда срабатывает это(как я понял, это вызов функции при повисании логики/биндера актора), и как его можно использовать в своих целях, при этом не используя системы этих авторов, но что бы результат был такой же(ЗЫ, у меня используется своя система таймеров, но никаких модульных систем типа слотов/сигналов и тп, не используется)

Изменено пользователем Viнt@rь
Ссылка на комментарий

Viнt@rь

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

 

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

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

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

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

Vint@rь, странно, что этот метод(функцию) ты только сейчас заметил ;-) Как уже написал ColR_iT, описание есть в "Справочнике по функциям и классам".

Учитывая некоторую неоднозначность восприятия, можно дать такое упрощенное пояснение:

1. Аргументов у этого метода в простейшем случае два: precondition и action :

level.add_call(precondition, action)

, но есть и иные варианты (см. в lua_help).

2. Этот метод запускает новый автономный поток Lua (thread), который не зависим(!) от привычного actor_binder:update(delta) и прочих потоков, т.е. будучи запущенным, этот поток вызывается в каждом игровом цикле после каждого апдейта актора (не зависимо завис апдейт или нет!) - и запускает проверку условия (precondition).

3. Этот метод по сути устанавливает коллбэк на вызов проверки условия (precondition) и по результату проверки значения возвращаемого precondition запускает (при true) заданное действие (action) и прекращает свою работу, уничтожая поток. При false - происходит тихое завершение цикла, до следующего игрового апдейта.

 

Т.о. в игре можно, например, организовать независимые циклы для апдейтов тех или иных схем/классов/... или различные варианты мониторинга зависших сторонних потоков.

 

Практическое применение также давно можно видеть в действии. Например, давно в моде SIMBION различные апдейты рестрикторов, погоды, новостей, оффлайн-алайфа и т.п. переведены именно на независимые апдейты на базе level.add_call. Можно видеть их использование и в модулях m_netpk и se_stor. Как сказано выше - это дает независимость от зависаний акторского апдейта да и подразгружает его, хотя конечно же все равно Lua выполняет все потоки 'последовательно'...

 

Ну а в упомянутых тобою скриптах от xStream и Malandrinus, этот метод, будучи независимым от сторонних потоков, как раз и выполняет роль "сторожа" (не только акторского биндера), контролируя "не зависли ли какие потоки", для которых заданы условия в precondition.

 

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

Следует иметь ввиду, что доп.поток - это и доп.ресурсы...

 

Небольшое 'warning!': В ЗП (CoP) это метод похоже имеет особенности... В модуле m_oflife (оффлайн-алафф) использование его для апдейта coroutine прерывается пока по непонятной для меня причине.

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

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

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

ColR_iT, Artos, спс :)

 

ColR_iT

 

Какой результат?

ну в смысле польза :)

 

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

да, я глядел, правда давненько это было

 

Artos

 

Vint@rь, странно, что этот метод(функцию) ты только сейчас заметил ;-)

заметил то я его давно, вот интерес(надобность), появился только сейчас :)

 

СтОит ли использовать этот метод "в свои целях"? Все опять же зависит от цели... Если аналогично "сторожить", или организовать свой автономный апдейтик для скрипта/класса - то конечно стОит, а вот для таймеров...

В своих целях в виде "сторожа", мб помнишь я писал про зависания биндера у меня?? вот для отлова этой "байды" :), а про свои таймера упомянул только из за того, что у меня не используются скрипты от xStream и Malandrinus

 

 

Практическое применение также давно можно видеть в действии. Например, давно в моде SIMBION различные апдейты рестрикторов, погоды, новостей, оффлайн-алайфа и т.п. переведены именно на независимые апдейты на базе level.add_call. Можно видеть их использование и в модулях m_netpk и se_stor. Как сказано выше - это дает независимость от зависаний акторского апдейта да и подразгружает его, хотя конечно же все равно Lua выполняет все потоки 'последовательно'...
Пишу это, не смотря на то, что у самого модуль таймеров именно на этом методе апдейтится. ;-)

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

Изменено пользователем Viнt@rь
Ссылка на комментарий

Я бы по другому сформулировал: "FPS напрямую зависит от апдейтов актора", а точнее полностью им соответствует, т.е. сколько раз в секунду обновился биндер актора - столько FPS (обновлений экрана в секунду) и имеешь.

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

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

 

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

Один минус, который стОит иметь ввиду уже указал - доп.ресурсы на обслуживание доп.потока. Хотя им скорее всего можно пренебречь.

Из плюсов:

- при разработке и/или отладке, когда те или иные потоки могут зависать (в особенности актрский), не лишним иметь возможность 'видеть' какие потоки работают, а какие зависли. Если все завязано на один поток, то довольно не просто разобраться в ситуации завис из-за таймера или иного события.

- (эксклюзивный случай) если некими методами "оживлять" зависшие потоки (например, это делает LuaCap by alpet), то некие потери имеет только зависший поток и его функционал, а те же таймеры продолжают "тикають как часики"...

 

Однако, для самого является до сих пор загадкою: "Почему разработчики GSC слили в один поток, например, обновление той же погоды иль классов (рестрикторы и т.п.)?" , хотя ранее были автономные потоки.

  • Нравится 1

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

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

Artos, обновления актора если и связаны с FPS рендера, то опосредованно, и уж точно их частота не одинаковая. Это совершенно точно. Более того, рендер и все его дела, в том числе и обновления с независимой частотой, как раз происходят в отдельном потоке Windows. Это в сущности единственный многопоточный момент в движке - отдельный поток для рендера.

 

Что же касается апдейтов актора и их связи с частотой апдейтов level.add_call. Я давно не занимался этими измерениями, но смутно помню, что частота апдейтов актора может быть равна или меньше частоте вызовов от level.add_call. Вроде как на старом компьютере и под патчем 1.0004 апдейты шли медленней, а сейчас (весьма быстрая машина и 1.0006) вроде как равны. Кроме того, частота апдейтов актора вообще говоря подчиняется общему правилу для апдейтов всех объектов, т.е. чем дальше от актора, тем медленней. Соответственно актор и его инвентарь обновляются с одной и той же, максимальной, частотой.

 

И более определённо я могу сказать насчёт природы вызовов level.add_call и также колбека fastcall. Они вызываются с одинаковой частотой и, насколько я знаю, эта частота просчёта игровой физики. Есть основания думать, что оба этих вызова исходно предназначались для скриптовой обвязки управления физическими объектами.

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

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

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

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

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

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

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

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

Войти

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

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

×
×
  • Создать...