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

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

Доброго времени суток господа Сталкеры! Подскажите, пожалуйста, как "зациклить" данный простой квест? Сделать так, чтобы его можно было бы выполнять неограниченное количество раз? В строке "condlist" необходимо прописать условие? Знающие люди, помогите, заранее благодарю!

 

[quest_vodka_give]
icon = ui_inGame2_Put_v_pripyat
prior = 2
storyline = false
title = {=actor_has_item(vodka)}vodka_barmen_prinesti_name, vodka_barmen_naiti_name
descr = vodka_barmen_descr
target = {=actor_has_item(vodka)}zat_a2_stalker_barmen
_0 = {+quest_vodka_done} complete
Ссылка на комментарий

Есть код.

Скрытый текст
--// Перебрать инвентарь по секциям и вытряхнуть наружу 
local tActorItems = {}
function drop_all_items()
    local f = function(dummy,item) 
        table.insert(tActorItems,item:section())    
    end
    db.actor:iterate_inventory(f,nil)
    drop_items()
    for i=1, #tActorItems do
        table.remove(tActorItems)
    end
end
function drop_items()
    local dropped
    for i=1, #tActorItems do  -- "Огласите весь список, пожалуйста!.."
        dropped = tActorItems[i]
        log3(dropped)        
        if dropped ~= "bolt" then
            local death_ini = ini_file("misc\\death_generic.ltx")
            local n = death_ini:line_count("keep_items")
            for i=0, n-1 do
                local keep_item = death_ini:r_line("keep_items",i,"","")
                if dropped ~= keep_item then
                    db.actor:drop_item(db.actor:object(dropped))
                end
            end
        end    
    end
end

 

И есть вопрос. 

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

Не выкидываются все предметы. Всегда остаются одни и те же, их можно удалить, повторно выполнив код. На поясе ничего нет.

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

F463bCzO.jpg?download=1&name=%D0%A1%D0%BA%D1%80%D0%B8%D0%BD%D1%88%D0%BE%D1%82%2022-10-2022%2021:20:05.jpg Fi4iiqT0.jpg?download=1&name=%D0%A1%D0%BA%D1%80%D0%B8%D0%BD%D1%88%D0%BE%D1%82%2022-10-2022%2021:21:29.jpg

Могу обойтись другим кодом, но просто интересно - почему так?

 

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

Здесь могла быть ваша реклама.

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

Таблица tActorItems пишется в переменную dropped целиком на каждой итерации сброса предметов. Возможно, должно быть dropped = tActorItems[ i ]?

Нужна ли сама таблица, если в процессе перебора инвентаря можно сверить секцию предмета со списком keep items и сразу сбросить предмет при отсутствии совпадения?

И еще непонятно, зачем чистить таблицу построчно после сброса предметов вместо полного обнуления tActorItems = {}.

 

Если задача скрипта сбросить всё, кроме квестовых и специальных предметов (болт, КПК), достаточно обойти инвентарь через inventory_for_each().

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

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

Шпаргалка

Ссылка на комментарий
7 часов назад, Norman Eisenherz сказал:

должно быть dropped = tActorItems[ i ]

Конечно же. Куда то потерялось, пока сюда нёс:biggrin:, иначе бы дальше вылета дело не пошло.

 

7 часов назад, Norman Eisenherz сказал:

Нужна ли сама таблица

Нет, есть такая возможность

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

    local actor = db.actor
    local cnt = actor:object_count()
    for i=0, cnt-1 do
        actor:drop_item(actor:object(i))
    end

 Но интересно стало, так сказать, для общего развития.

 

7 часов назад, Norman Eisenherz сказал:

вместо полного обнуления tActorItems = {}

Как именно? Моего опыта с таблицами на большее не хватает.

Здесь могла быть ваша реклама.

Ссылка на комментарий
13 минут назад, mole venomous сказал:

Как именно? Моего опыта с таблицами на большее не хватает.

 именно так   tActorItems = {}

закрытые фигурные скобки обнуляют таблицу

  • Спасибо 1
Ссылка на комментарий
5 минут назад, ted.80 сказал:

именно так   tActorItems = {}

Ок. А ваш Кэп подумал, её так лишь объявляют перед кодом...

Всех благодарю, но

12 часов назад, mole venomous сказал:

Не выкидываются все предметы

12 часов назад, mole venomous сказал:

почему так?

так и не ясно.

Здесь могла быть ваша реклама.

Ссылка на комментарий
7 минут назад, mole venomous сказал:

её так лишь объявляют перед кодом

Точно так, не существующая до этого таблица создаётся, а существующая очищается :528:

Ссылка на комментарий
13 часов назад, mole venomous сказал:

почему так

Потому что db.actor:object(dropped) ищет не конкретный предмет, а первый попавшийся предмет с секцией, равной секции dropped.

Ты заметил, что после первого выкидывания остаются в инвентаре только те предметы, количество которых больше 1? Можно предположить, например, что функция drop_item удаляет предмет не одномоментно, а с некоторым запаздыванием, и когда ты ищешь следующий предмет с такой же секцией, всё время находится первый из них, который уже должен был удалиться к тому времени.

Чтобы этого избежать, можно попробовать перейти на работу с идентификаторами вместо секций:

table.insert(tActorItems,item:id()) -- запоминаем идентификатор вместо секции
db.actor:drop_item(level.object_by_id(dropped)) -- ищем объект по идентификатору

В остальном код будет идентичным.

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

Не выкидываются все предметы

попробуй вот так:

function dropall()
	for i=0,db.actor:object_count()-1 do
	local item = db.actor:object(i)
		if item and item:section() ~= "bolt" and item:section() ~= "device_pda" and item:section() ~= "device_torch" then
			local death_ini = ini_file("misc\\death_generic.ltx")
			local n = death_ini:line_count("keep_items")
			for i=0, n-1 do
				local keep_item = death_ini:r_line("keep_items",i,"","")
				if item:section() ~= keep_item then
					db.actor:drop_item(item)
				end
			end
		end
	end
end

 

  • Согласен 1
Ссылка на комментарий
5 минут назад, ted.80 сказал:
for i=0,db.actor:object_count()-1 do

Так делал - всё хорошо. А сейчас решил через

 

14 часов назад, mole venomous сказал:
db.actor:iterate_inventory

и таблицу. Опять же, 

 

2 часа назад, mole venomous сказал:

для общего развития

 

Здесь могла быть ваша реклама.

Ссылка на комментарий
2 hours ago, Kirgudu said:

Можно предположить, например, что функция drop_item удаляет предмет не одномоментно, а с некоторым запаздыванием

Даже и предполагать не нужно. Это так и есть. На следующем апдейте предмет будет выброшен. А пока только помечен к выбрасыванию и это можно проверить методом dropped_mark или как-то так. Я вечно названия забываю.

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

@mole venomous

1. При построчном чтении конфига выводятся три переменных: пустышка, имя параметра, значение.

2. Конфиг [keep_items] достаточно вычитать один раз – см. последний пример.

Spoiler
function drop_all_items()
	local function fx(item)
		db.actor:drop_item(item)
	end

	db.actor:inventory_for_each(fx)		-- кроме квестовых и специальных предметов
end

 

Spoiler
local t = {}

function drop_all_items()
	local function fx(dummy, item)
		t[#t +1] = item					-- можно заносить в таблицу сами предметы – drop_item позволяет обходить пустышки
	end

	db.actor:iterate_inventory(fx, nil)
	
	for i = 1, 5 do						-- несколько случайных предметов
		local k = math.random(#t)		-- случайный ключ
		db.actor:drop_item( t[k] )
		table.remove(t, k)				-- построчная очистка
	end
end

 

Spoiler
local keep = {}				-- полный список; заполняется один раз
keep.bolt = true
keep.device_torch = true
keep.device_pda = true

local death_ini = ini_file("misc\\death_generic.ltx")
local n = death_ini:line_count("keep_items")

for i = 0, n -1 do
	local dummy, sect, bool = death_ini:r_line("keep_items", i, "" , "")		-- три переменных: пустышка, параметр, значение (в данном случае true для всех)
	keep[sect] = bool
end


local items = {}

function drop_all_items()
	local function list(dummy, item)
		if not keep[ item:section() ] then				-- сверка по ключу (вместо перебора)
			items[#items +1] = item						-- можно заносить в таблицу сами предметы – drop_item позволяет обходить пустышки без вылета
			-- items[#items +1] = item:id()				-- вариант с id
		end
	end

	db.actor:iterate_inventory(list, nil)
	
	for i = 1, #items do
		db.actor:drop_item( items[i] )
		-- db.actor:drop_item( level.object_by_id( items[i] ) )		-- вариант с id
	end

	items = {}					-- полная очистка
end

 

 

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

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

Шпаргалка

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

Нашел упоминания о том, что функции, доступные в скриптах, можно временно подменять своими:
https://www.amk-team.ru/forum/topic/11584-yazyk-lua-obschie-voprosy-programmirovaniya/page/13/#comment-657328
https://www.amk-team.ru/forum/topic/11584-yazyk-lua-obschie-voprosy-programmirovaniya/page/55/#comment-994377

 

Ради эксперимента попытался изменить условия прохода под мостом в ТЧ: пробовал как показано ниже, пробовал указывать в безымянной функции аргументы и дописывать к исходной функции _G. – никакой реакции.

Spoiler
escape_dialog.has_soldiers_bribe = function()
	return actor:money() >= 1
end

escape_dialog.give_soldiers_bribe = function()
	dialogs.relocate_money(npc, 1, "out")
end

 

Есть ли разница, в каком именно скрипте указан код с подменой функций?

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

Шпаргалка

Ссылка на комментарий
5 часов назад, Norman Eisenherz сказал:

Есть ли разница, в каком именно скрипте указан код с подменой функций?

Есть разница в том, в каком порядке загружаются и инициализируются твой скрипт и целевой.

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

Об этом. кстати, уже написано в постах по приведённым ссылкам.

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

Назвал новый скрипт последней буквой алфавита – вызова новых функций все равно нет. Опять же, пробовал добавлять _G. перед старыми именами и указывать аргументы при замене. Каким должен быть правильный формат записи?

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

Шпаргалка

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

Правильный формат описан в тех постах.

Используй вызов prefetch("модуль_с_подменяемой_функцией") в _g.start_game_callback() для принудительной заблаговременной загрузки.

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

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

В тех постах указано два разных формата: script.fx = function() без аргументов и _G.script.fx = function(аргументы) с какой-то промежуточной подменой (если я правильно понял, это сохранение старой функции и вызов ее как есть перед новыми действиями).

Сработал в итоге вариант script.fx = function(аргументы), но только через prefetch нового скрипта.

 

Теперь главный вопрос: какие дополнительные возможности дает подмена на ходу по сравнению с прямым редактированием исходных скриптов?

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

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

Шпаргалка

Ссылка на комментарий
1 час назад, Norman Eisenherz сказал:

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

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

Нужно это или нет в конкретном моде, можно решить самостоятельно.

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

Другими словами, кроме сохранения исходных файлов разницы нет, так как изменения в скриптах учитываются только при перезагрузке, но не в процессе игры?

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

Шпаргалка

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

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

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

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

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

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

Войти

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

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

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