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

Язык Lua. Общие вопросы программирования


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

С чего начинать и где взять.

 

Установка Lua:
http://www.amk-team.ru/forum/index.php?showtopic=11584&p=629106

 

Руководство «Программирование на языке Lua», третье издание:
http://www.amk-team.ru/forum/index.php?showtopic=11584&p=905308

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

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

Скрытый текст

local t = {{{{{}}}}} -- 4 вложенных
local g = t
local tst = t[1][1][1]

print(t[1][1][1][1]) -- table:
t[1][1] = t[1][1][1]
print(t[1][1] ==  tst, t[1][1][1][1] ) -- true, nil срезалась и "хвост" подтянула!
-- А так нельзя
print( t[1][1][1][1] ) -- table:
local a = t[1][1]
local b = t[1][1][1]
a = b
print( t[1][1][1][1] ) -- table: хвост не подтянут!
print( t[1][1] == g[1][1]) -- true
-- и срез не произошёл! Проверим ещ переменные:
print( a == g[1][1], b == g[1][1], a==b) -- false, false, true
print(a == g[1][1][1], b == g[1][1[1]]) -- true, true

print(a == t[1][1][1], b == t[1][1[1]]) -- true, true
print(t==g) -- true

 


Как можно программно реализовать правильный срез таблицы из "башни", если вложенную таблицу на определённом уровне я получаю циклом:

local pred = t
while (pred) do
    pred = pred[1]
   if pred == t[1][1] then
        pred = pred[1] -- не работает так. см 2 пример
   end
end

 

Изменено пользователем Graff46
  • Нравится 1
Ссылка на комментарий
4 часа назад, Graff46 сказал:

a = b print( t[1][1][1][1] ) -- table: хвост не подтянут! print( t[1][1] == g[1][1]) -- true

Сначал ты в a положил t[1][1], потом t[1][1][1]. Почему в t что-то должно было измениться?

Если думать в терминах ссылок, то сначала в а положили ссылку на таблицу второго уровня, потом в а положили ссылку на таблицу 3 уровня. Таблица t при этом никак не модифицировалась.

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

@abramcumner Я думал что я в а положил t[1][1] , потом t[1][1] приравнял к t[1][1][1], но это работает не так. Вот тут товарищ расписал, нужно было всего лишь таблицу уровнем ниже взять и к а приписать индекс.

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

Часто бывают ситуации когда можно приравнять какой-то объект к функции и эта ф-ция будет вызываться при определенных условиях и параметрах, но часто этого мало - хочется несколько ф-ций повесить на 1 объект. Для этой цели я написал 2 реализации. Собственно хочется узнать какой способ более приемлем,  я делал тест на множественное выполнение 4 функций (2^20 раз) - по времени результат приблизительно равный.

Скрытый текст

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


local noop = function() end

local storage = {noop}
setmetatable(storage, {__call = function(slf, ...) return slf[1](...) end})
local b = storage

function add(f) -- добавить ф-цию в линию выполнения
    local texe = {noop, f}
    setmetatable(texe, {__call = function(self, ...)
        self[2](...); 
        return self[1](...)
    end})
    b[1] = texe
    b = texe
end

function find(f_obj) -- поиск ф-ции из линии, если нашлась - возвращает её родительскую таблицу (сама найденная ф-ция 2 элемент в таблице)
    local stack, prevStack = storage, storage
    while (type(stack) == "table") do 
        stack = stack[1] 
        if stack[2] == f_obj then
            return prevStack
        end
        prevStack = stack
    end
end -- не громоздкий поиск ф-ции в линии

function del(fun) -- удаление ф-ции из линии
    local a = find(fun)
    a[1] = a[1][1] 
end

 

2-й способ:

Скрытый текст

local line = {test, test2, test3, test4}
    
local function iniciator(...)
    for i=1, #line do
        line[i](...)
    end
end

setmetatable(line, {__call = function(slf, ...) return iniciator(...) end})

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

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

Изменено пользователем Graff46
Ошибки исправлял
Ссылка на комментарий

Привет.

Ребяты, помогите с шаблоном для удаления комментариев из xml.

Пробовал так:

<!%-%-.+%-%->

Но захватывается всё, начиная с первого и по последний комментарий. Ну, это ожидаемо. А так

<!%-%-.-%-%->

Вообще ничего не захватывает, хотя, по идее, должно...

 

upd: вопрос снят, очепятка была :blush:

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

Аддон для ОП-2.09.2: Яндекс/Google/GitHub

naxac.gif

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

@Graff46, мне своё нравится делать, пусть даже это будет велосипед, который уже тысячу раз изобрели.

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

Аддон для ОП-2.09.2: Яндекс/Google/GitHub

naxac.gif

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

Здрасьте.

 

Задача: вызвать несколько функций при чтении нетпакета, составляя их названия из строки "r_" и типа переменной. На выходе должно получиться r_u8(), r_stringZ(), r_float() и т. д. Шаблон, насколько мне известно, такой: namespace["func"](arg1, arg2). Пример вызова функции без привязки к объекту: _G["time" .. "_global"]().

Тест:

net_packet["r_u32"]() – вылет "pure virtual function call" (ожидаемо – нет ссылки на нетпакет)
• pk:net_packet["r_u32"]() – вылет "attempt to index global 'script_filename' (a nil value)"

 

Каким должен быть синтаксис при таком вызове функций?

Мини-моды: ТЧ ЧН ЗП

Шпаргалка

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

@Norman Eisenherz

pk = net_packet()

-- Если функция без аргументов
pk["имя_функции"](pk)

-- Если функция с аргументами a, b, c
pk["имя_функции"](pk, a, b, c)

 

  • Нравится 1

S.T.A.L.K.E.R. CoP Objects (upd 15.11.24)

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

Не уверен я, куда этот вопрос писать, но попробую сюда.

Вопрос про объявление и наследование классов в Lua, c Luabind-ом из OGSR.


 

Скрытый текст

 

Код примерно такой структурно


class "A"
function A:__init()
end
function A:__finalize()
end
***
class "B" (A)

function B:__init (...) super()
	self.params = {...}
end
***
class "C" (B)

function C:__init (...) super(...)
end
***
class "D" (C)

function D:__init (...) super(...)
end
***
class "E" (D)

function E:__init (...) super(...)
end
***
class "F" (E)

function F:__init (...) super(...)
end
*** // и т.д.
function Create()
same_object = G_script.G(...)
end
-- Где '***' - обозначают разные файлы...

Возвращает примерно такой лог


[19.11.20 15:41:07.174] expected class [B] to derive from or a newline
[19.11.20 15:41:07.181] ***************************[ScriptCrashHandler]**********************************
[19.11.20 15:41:07.181] stack traceback:
	[C]: at 0x018000bee4
	....a.l.k.e.r_ogsr\gamedata\scripts\script_B.script:20: in main chunk
	[C]: in function '__index'
	....e.r_ogsr\gamedata\scripts\script_C.script:15: in main chunk
	[C]: in function '__index'
	...a.l.k.e.r_ogsr\gamedata\scripts\script_D.script:15: in main chunk
	[C]: in function '__index'
	....a.l.k.e.r_ogsr\gamedata\scripts\script_E.script:15: in main chunk
	[C]: in function '__index'
	...a.l.k.e.r_ogsr\gamedata\scripts\script_F.script:15: in main chunk
	[C]: in function '__index'
	....a.l.k.e.r_ogsr\gamedata\scripts\script_G.script:15: in main chunk
	[C]: in function '__index'
	....t.a.l.k.e.r_ogsr\gamedata\scripts\subtask.script:270: in function 'Create'

Где строка "expected class [ Х ] ... " неизменно указывает на тот класс, который является потомком класса, не имеющего родителей.

Т.е. если например я C наследую от A - ругаться лог будет на C.

Если же С наследует от B, B наследует от A, а для A я создам новый класс-родитель X. Так что А наследует от X, а X ни от кого - то ругаться будет на A.

Разве я не могу наследовать от скриптовых классов?

Если сам по себе скриптовый класс (т.е. просто вот это:)


class "same"
function same:__init()
...
end
function same:method0()
...
end
, etc...

Исправно работает.

Конструкции вроде биндеров


class "actor_binder" (object_binder)
function actor_binder:__init (obj) super(obj)
...

Тоже работают, наследуя от классов, объявленных в движке. object_binder в данном случае.

А от скриптового наследовать нельзя?

 

* * *

 

По-копавшись, обнаружил искомое в старом m_netpk.script, артосо-модуль т.е.

Там объявлен class "net_base" - не наследующий ни от кого, и от него наследуются другие классы. Т.е. там это работало, хотя модуль не под OGSR создавался.

А тут? Что я делаю не так, или что надо делать не так, объявляя наследование классов друг от друга в скриптах под OGSR. Проясните, кто в курсе.

 

 

Мод, где не бывает одинаковых путей - Судьба Зоны. (Лучшее, что у меня получилось на 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.

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

Здрасьте.

 

Если this["подстановка"]() позволяет вызвать функцию по строковому имени из текущего скрипта, то для чего нужны конструкции вида this.точное_имя(), если прямой вызов по имени функции и так действует в текущем скрипте?

 

Примеры:

ЗП [utils.script] this.vector_copy_by_val()

ТЧ [uilts.script] и [xr_talker.script] this.vector_copy_by_val() – две разные функции, но каждая вызывается только в своем скрипте

Мини-моды: ТЧ ЧН ЗП

Шпаргалка

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

Если ты спрашиваешь, то тебе это сейчас точно не нужно. Когда и если понадобится, ты сразу поймёшь. Мне пару раз нужно было. Если я правильно помню, у меня в скрипте была функция с таким же именем, как и в _g.script, но с другим содержимым конечно. Вот для её вызоваа я и использовал вариант через this. Это если я ничего не перепутал за давностью. Кажется ещё какие-то заморочки были, но я уже не помню. 

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

IDE: ZeroBraine. Lua 5.3

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

Вариант с ошибкой:

Скрытый текст


math.randomseed(os.time())
function foo (t, desc)
	local itera = 0
	local skip = {}

		function bar ()
			local val = math.random(1, #t)
			if itera == #t then
				skip = {}; 
				itera = 0
			end
			if skip[val] then
				return bar()
			else
				skip[val] = true
				itera = itera + 1
				print(desc..':', t[val])
			end
		end
		return bar
end

local t1 = {'red', 'blue', 'green', 'white', 'yellow'}
local t2 = {'apple', 'orange', 'cherry', 'potatoes', 'tomato'}
local c1 = foo(t1, 'color')
local c2 = foo(t2, 'fruits')

for i = 1, 20 do
	c1()
	if i % 5 == 0 then 
		print('------------------')
	end
end

 

его вывод:

Скрытый текст

Программа запускается как '"E:\1\lua\ZeroBraneStudio\bin\lua53.exe" -e "io.stdout:setvbuf('no')" "E:\1\lua\ZeroBraneStudio\my\test1.lua"'.
Программа 'lua53.exe' запущена в 'E:\1\lua\ZeroBraneStudio\my' (pid: 1816).
color:    blue
color:    white
color:    yellow
fruits:    apple
color:    red
------------------
fruits:    cherry
fruits:    potatoes
fruits:    tomato
fruits:    orange
fruits:    cherry
------------------
color:    green
color:    white
color:    blue
color:    red
fruits:    orange
------------------
fruits:    apple
color:    green
fruits:    tomato
color:    yellow
color:    white
------------------
Программа завершена за 0.05 секунд (pid: 1816).

Исправленный вариант:

Скрытый текст


math.randomseed(os.time())
function foo (t, desc)
	local itera = 0
	local skip = {}
	return function ()
		function bar ()
			local val = math.random(1, #t)
			if itera == #t then
				skip = {}; 
				itera = 0
			end
			if skip[val] then
				return bar()
			else
				skip[val] = true
				itera = itera + 1
				print(desc..':', t[val])
			end
		end
		return bar()
	end
end

local t1 = {'red', 'blue', 'green', 'white', 'yellow'}
local t2 = {'apple', 'orange', 'cherry', 'potatoes', 'tomato'}
local c1 = foo(t1, 'color')
local c2 = foo(t2, 'fruits')

for i = 1, 20 do
	c1()
	if i % 5 == 0 then 
		print('------------------')
	end
end

 

Вывод:

Скрытый текст

Программа запускается как '"E:\1\lua\ZeroBraneStudio\bin\lua53.exe" -e "io.stdout:setvbuf('no')" "E:\1\lua\ZeroBraneStudio\my\test1.lua"'.
Программа 'lua53.exe' запущена в 'E:\1\lua\ZeroBraneStudio\my' (pid: 7496).
color:    yellow
color:    blue
color:    red
color:    white
color:    green
------------------
color:    yellow
color:    white
color:    green
color:    blue
color:    red
------------------
color:    green
color:    yellow
color:    blue
color:    red
color:    white
------------------
color:    yellow
color:    white
color:    blue
color:    red
color:    green
------------------
Программа завершена за 0.05 секунд (pid: 7496).

Я понимаю, что где то потерял переменные, но где и как? В 1м случае в вывод попали значения из 2-х таблиц, если вызов ф-ции был для одной таблицы?

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

@Graff46, крутой код, ничего не скажешь...

1. А зачем в функции bar() рекурсия? Почему не использовать repeat-until? Представь стек вызовов если в таблице t будет 1000 значений.

2. Обязательно хранить в c1 и c2 замыкание bar() со всеми переменными? Особенно с параметром t, в котором может быть большая таблица. Лучше пересмотреть реализацию в сторону более "простого" кода.

 

Откровенно говоря - не знаю где проблема. Возможно в том, что в первом примере функция bar() именованная.

S.T.A.L.K.E.R. CoP Objects (upd 15.11.24)

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

Здрасьте.

 

Задача: показать разницу в работе модификаторов поиска * + - ?. Один пример удалось подобрать так, чтобы результат поиска отличался для всех вариантов, но хочется чего-то более наглядного. Может, кому попадалось более интересное сочетание строки и шаблона?

Spoiler
local str = "aa1a22a333"
local t = {}
for x in str:gmatch("a%d#") do
	t[#t +1] = x
end

#
*	a, a1, a22, a333		-- буква и 0+ цифр
+	a1, a22, a333			-- буква и 1+ цифра
-	a, a, a, a			-- буква и 0+ цифр, короткое совп.
?	a, a1, a2, a3			-- буква и 0/1 цифра

 

 

Мини-моды: ТЧ ЧН ЗП

Шпаргалка

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

Почему нет статьи про анимации?

Уже весь сайт перелопатил, но так и не нашел нужной мне статьи.
Заметил, что довольно мало информации о работе с анимациями рук  гг и неписей.
Вообще интересует как  можно вызвать определенную анимацию через функцию actor_binder:on_item_take
пока только изучаю Lua  и потому сложно самому что-то толковое сделать   
  

Добавлено  Murarius,

Перемещено.

Ссылка на комментарий
10.05.2024 в 20:02, Личность сказал:

Почему нет статьи про анимации?

Раньше точно были...

Если на пальцах, в сталкере анимация это некая последовательность данных записанная в модель.

В современных движках вроде OGSR, есть методы вызова нужной анимации по имени, у определенного объекта.

Были ли они в оригинальном движке ТЧ, честно говоря не помню. Если были, то их должно быть возможно найти тут.

Мод, где не бывает одинаковых путей - Судьба Зоны. (Лучшее, что у меня получилось на 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.

Ссылка на комментарий
13.05.2024 в 05:48, Zander_driver сказал:

Были ли они в оригинальном движке ТЧ, честно говоря не помню. Если были, то их должно быть возможно найти тут.

Только для мировой модели объекта - play_cycle. В случае с НПС/монстрами play_cycle практически бесполезен, так как перебивается движком или другими скриптовыми схемами. Подходит по сути только для неживых объектов.

Для худа оружия (hud_item) проиграть анимацию на оригинальном движке нельзя.

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

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

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

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

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

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

Войти

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

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

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