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

Язык 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
Ссылка на комментарий

@Graff46,

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

 

Короче, тебе нужно читать файл средствами самого сталкира. класс reader тебе в помощь.

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

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

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

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

 

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

@Malandrinus, Файл в котором я работаю это сейв ТЧ, Если его открыть текстовым процессором, то можно увидеть как некоторые ресурсы (части логики, инфопоршни, переменные из пстор и т.д.) хранятся "прямым текстом", вот я и решил, что читать файл как текстовой.

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

 

 

класс reader тебе в помощь
Им можно воспользоваться до загрузки игры?

 

 

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

reader Это который при загрузке в биндере? Я им не смогу воспользоваться до загрузки игры из гл. меню...

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

@Graff46,

local file = getFS():r_open("$game_config$", "savename.sav")
local str = file:r_stringZ()
Пользоваться можно и до загрузки уровня/алайфа. Изменено пользователем naxac

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

naxac.gif

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

@User_X.A.R26@Malandrinus, Ура! получилось! Не понадобились

 

бинарное же посимвольное чтение и собственная реализация функций поиска текста

я то хотел уже из хекс редактора шаблоны текста брать, но даже открыв файл как бинарный он сохранил свою "текстовую" структуру. Вот мой код 

 


function load_dialog:load_game_internal()	
	local console = get_console()
	local list = self:GetListWnd("list_window")	

	if list:GetSize()==0 then return end

	local index = list:GetSelectedItem()
	
	if index == -1 then return end
		
	local item  = list:GetItem(index)
	local fname = item.fn:GetText()
	
	if (alife() == nil) then
		local file = io.open(getFS():update_path("$app_data_root$", "savedgames\\") .. fname .. ".sav", "rb")
		get_console():execute(file:read("*a"):match("osen%d"))
		file:close()
		console:execute	("disconnect")	
		console:execute	("start server(" .. fname .. "/single/alife/load) client(localhost)")	
	else
		console:execute	("load " .. fname)	
	end
end 

 

Сохранение загрузилось, после выхода я вижу в логе 

! Unknown command:  osen2 

Теперь можно делать самому враппер сейвов...


 

 

local str = file:r_stringZ()
Такое не сделать наверно без загрузки уровня? Изменено пользователем Graff46
  • Нравится 1
Ссылка на комментарий

 

 

Пользоваться можно и до загрузки.
я попробовал 
[error]Arguments     : LUA error: ... of fukushima\gamedata\scripts\ui_load_dialog.script:275: attempt to call method 'r_stringZ' (a nil value)
 

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

От кого, так от тебя я таких дебильных вопросов точно не ожидал. Или в тех пяти строчках кода что-то непонятно

А вот я почему-то не удивлён твоему хамству. Могу только повторить, что твой код не соответствует твоему описанию "значение идет по кругу". Значение в приведённом алгоритме не идёт по кругу, а застревает в минимуме или максимуме. У подобной операции нет названия, а ближе всего по смыслу, как я сказал, получение остатка от деления, с помощью которой и делают обычно хождение по кругу.

 

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

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

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

 

Ссылка на комментарий
file:r_stringZ()

Это методы reader'а? Я не могу найти описание этого класса на нашем форуме и на близлежащих, из луа _хелп ни чего не понял, там только перечислены методы. Если можно, тыкните носом на описание класса reader.

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

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

 

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

local low_boundary = 3
local upper_boundary = 7
local current_position = 5
for i=1,20 do
    print(current_position)
    current_position = current_position + 1
    current_position = low_boundary + math.fmod(current_position - low_boundary, upper_boundary - low_boundary + 1)
end
 

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

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

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

 

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

Уважаемое сообщество, хотел бы поинтересоваться Вашим мнением по такому вопросу:

Все видели, наверное, мод автопаузы, который использует инжектор кода через подмену, например, апдейта актора. Но xray считает по другому, и на такие попытки разместить именно в коде класса функцию он уверенно сообщает, что "RUNTIME ERROR - no static '_update' in class 'actor_binder'". Вот меня и интересует - 

1) Отходит ли от стандарта языка такая технология инжектора кода? 

2) если язык это поддерживает - в данном случае luabind "не прав" (ибо сообщение о ошибке - выдает именно он)?

3) игнорировать ли мне такое сообщение или переписать код в соответствие со стандартами языка?

Благодарю за Ваше мнение!


не столь секретен, чтобы ограничиваться лишь туманными намеками

 

- эээ... да никаких секретов... у меня в тексте сообщение так и написано - "мод автопаузы", впервые мне встретился, наверное в НС в каком то репаке. в ооп еще был. мод, который после загрузки добавляет паузу на нажатие любой клавиши (ТЧ). inj.script  - там есть такой код, который не нравиться xray 1.0007

 

local function inj_main(func_name,flag,fn,narg)
 if not _G.bind_stalker.actor_binder["_"..fn] then
 _G.bind_stalker.actor_binder["_"..fn] = {}
  if narg==1 then
   _G.bind_stalker.actor_binder["_"..fn][1] = _G.bind_stalker.actor_binder[fn]
   _G.bind_stalker.actor_binder[fn] = function(...)
    for _,f in pairs (_G.bind_stalker.actor_binder["_"..fn]) do f(...) end end
  else
   _G.bind_stalker.actor_binder[fn.."_"] = _G.bind_stalker.actor_binder[fn] or function()end
   _G.bind_stalker.actor_binder[fn] = function(...) local arg={...}
    _G.bind_stalker.actor_binder[fn.."_"](...)
    for _,f in pairs (_G.bind_stalker.actor_binder["_"..fn]) do
     f(arg[narg])
    end
   end
  end
 end
 _G.bind_stalker.actor_binder["_"..fn][func_name] = loadstring('return _G["'..string.gsub(flag and func_name or "_","%.",'"]["')..'"]')()
end
function inj_update(func_name,flag)
	inj_main(func_name,flag,"update",1)
end

 

 

в данном случае вызов в классе актора update подменяется на 2-а вызова , один - сохраненная функция (оригинальный actor_binder.update), второй  - функция, переданная как параметр.

Вот собственно. если такой подход применяется к функции в модуле - движок не возражает, если к классу - вызывает runtime error, описанная выше.

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

@Winsor, попробуй так:

function inj_update(f)
  _G.actor_update = _G.bind_stalker.actor_binder.update
  _G.bind_stalker.actor_binder.update = function ( ... )
    _G.actor_update(...)
   f(...)
  end
end
Где f - подключаемая функция. Да, и подключать можно только после инициализации класса, иначе изменений не будет.

 

А вообще, ИМХО, метод так себе. Проще - написать нечто на подобии скрипта xr_s из ЗП, и через него подключать-отключать что угодно.

Изменено пользователем naxac
  • Спасибо 1

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

naxac.gif

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

 

 

можно только после инициализации класса

Перенеся сохранение функции в модуль - избавился от ошибки.

данную подмену необходимо делать после загрузки модуля но до инициализации класса , методы которого пытаемся подменить. Движок создает, например, биндер актора один раз, и любые подмены после вызова __init ни к чему не приводят. Но это частности. Интересовала вообще корректность такого подхода, насколько он оправдан.

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

Движок создает, например, биндер актора один раз, и любые подмены после вызова __init ни к чему не приводят.

Странно. У меня, в частности,с биндером актера, это работало (в ОП-2 такое использовал).

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

naxac.gif

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

Код странен. Я вообще не понял, что он должен делать.

 

"RUNTIME ERROR - no static '_update' in class 'actor_binder'" - именно так, да.

 

 

local s = "_" .. fn
local binder = _G.bind_stalker.actor_binder
local t = binder[s]
if not t then
	t = {}
	binder[s] = t
	if narg==1 then
		t[1] = binder[fn]
		binder[fn] = function(...)
		for _,f in pairs ( t ) do
			f(...) end
		end
binder[fn] = function(...) - вот это вот что и зачем ?

И зачем в цикле пытаться вызвать как функцию единственный элемент какой-то таблицы, который вообще то-ли есть, то-ли нет ?

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

 что он должен делать

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

 

вот это вот что и зачем

- это и есть непосредственно сама замена (fn=="update" ), внутри которой и вызывается свой код + сохраненная версия. по поводу цикла - ничего не скажу. Возможно автор предполагал через дополнительные параметры при первоначальном инжекте добавлять в таблицу t несколько функций, и таким образом их вызывать.

 

в том же скрипте автопаузы есть

local function inj_mm_on_kbd(func_name)
	local name = "ap_mm_on_kbd"
	_G[name] = _G.ui_main_menu.main_menu.OnKeyboard
	_G.ui_main_menu.main_menu.OnKeyboard =
		function(...)
			local arg={...}
			if not loadstring('return _G["'..string.gsub(func_name,"%.",'"]["')..'"]')()(arg[1],arg[2],arg[3]) then
				return _G[name](...)
			end
			return true
		end
end

 

тут подмена вызова нажатий клавиш в главном меню.

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

Привет всем.

Подскажите, можно ли через loadstring выполнить функцию, в параметр которой нужно передать строку? У меня получается только с числом. Или, может, как-то иначе можно это сделать: есть функция строкой и параметры разных типов (тоже строками), надо выполнить эту функцию?

 

upd: решил так:

function run(func, ...)
  ...
  local t = {...}
  for i,v in ipairs(t) do
    if tonumber(v) then t[i] = tonumber(v)
    elseif v == 'true' then t[i] = true
    elseif v == 'false' then t[i] = false
    end
  end
  return loadstring("return "..func)()(unpack(t))
end
Изменено пользователем naxac

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

naxac.gif

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

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

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

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

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

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

Войти

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

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

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