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

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

Подскажите, как удалить артефакт из инвентаря и рестриктор? 

и то и другое пытался удалить через alife():release(), однако безуспешно. 

Артефакт мне нужно забрать (без сообщения о том, что он был изъят), а в рестрикторе у меня такая логика: 

[logic]
active = sr_particle, nil
[sr_particle]
name = anomaly2\oasis_way
path = esc_vagon_way
mode = 2
looped = true

Т.е. мне партикл убрать нужно. И вот при:

local se_obj = alife():object("rest_name_vagon")
if se_obj then
alife():release(se_obj, true)
end

Партикл остаётся, т.е рестриктор никуда не делся. Я даже логику пробовал менять, изменял активную секцию, и тд. Партикл не уходит. В общем, подскажите, пожалуйста. 

God save Hatsune Miku!

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

Партикл остаётся, т.е рестриктор никуда не делся. Я даже логику пробовал менять, изменял активную секцию, и тд. Партикл не уходит. В общем, подскажите, пожалуйста. 

Попробуй закомментировать строки:

local se_obj = alife():object("rest_name_vagon")
--if se_obj then
alife():release(se_obj, true)
--end

 

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

@abramcumner фигу, даже так нифига. Ничего уже не понимаю.  Если в СДК удалить этот рестиктор, то при срабатывании получаю вполне ожидаемый вылет: 

 

Expression    : assertion failed
Function      : CALifeSimulator__release
File          : deep deep in space
Line          : 666
Description   : Object to release is a zero pointer

Т.е. как бы сомнений нет, что он его удаляет, в случае когда он есть. 

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

God save Hatsune Miku!

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

@Labadal похоже, что ГСЦ такого не ожидала. И рестриктор удаляется, а партиклы не отключаются.

 

Попробуй сначала перевести рестриктор в другую секцию/nil и только потом удалять.

 

Или можно в bind_restrictor.script в функции function restrictor_binder:net_destroy()

if st.active_scheme then
  xr_logic.issue_event(zone, st[st.active_scheme], "deactivate") -- добавить отправку события отключения схемы перед удалением
  xr_logic.issue_event(zone, st[st.active_scheme], "net_destroy")
end

 

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

Знатоки ТЧ, прошу помощи.
Захотелось мне добавить в циклические квесты помимо стандартного описания, прописываемого в xml (по типу "мне поступил заказ на медузу, нужно срочно достать, берёшься?"), ещё и список наград, чтобы выглядело так:
 

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

Слышал поверье, что зуб кровососа притягивает удачу? Будто бы того, кто на шее носит такой зуб, аномалии отпускают, и артефакты сами в руки идут? В общем, это всё фигня, но есть болваны, которые верят и готовы платить хорошие деньги. Принесешь челюсть кровососа, я тебе хорошо заплачу.
За это в награду ты получишь:
"иконка" Деньги: 3000
"иконка" Предметы: Дробь 20, бинт, аптечка

Как всё это добавить я разобрался, и иконки и текст нормально подставляются, но я никак не могу получить id квеста (напр. tm_monster_part_1)
Вот так сейчас выглядит код:
 

Скрытый текст
function CRandomTask:action_task_show_reward(npc, actor)
	local task_desc = self.task_info["tm_monster_part_1"]
	local task_texture, task_rect
	local message
		task_texture, task_rect = get_texture_info("ui_iconsTotal_found_money", "ui_iconsTotal_found_money")
		db.actor:give_talk_message(tostring(self.task_info[self.task_id_by_init_phrase_id[p3]]), task_texture, task_rect, "iconed_answer_item")
	
	if task_desc.reward_money ~= nil then
		task_texture, task_rect = get_texture_info("ui_iconsTotal_found_money", "ui_iconsTotal_found_money")
		message = game.translate_string("reward_list_money").." "..tostring(task_desc.reward_money)
		db.actor:give_talk_message(message, task_texture, task_rect, "iconed_answer_item")
	end
	
	if task_desc.reward_item ~= nil then
		task_texture, task_rect = get_texture_info("ui_iconsTotal_found_thing", "ui_iconsTotal_found_thing")
		message = game.translate_string("reward_list_items")
		for kk,vv in pairs(task_desc.reward_item) do
			message = message..", "..game.translate_string(news_manager.get_inv_name(vv))
		end
		db.actor:give_talk_message(message, task_texture, task_rect, "iconed_answer_item")
	end
end

 

И мне нужно вместо указанного мною id "tm_monster_part_1" как-то получить id выбранного в диалоге квеста. Как это сделать? Скрипт task_manager.script стандартный. Смотрел, как получают в других функциях, пробовал разные варианты, но что-то ни один не подошёл.

Вот функции добавления диалога и вызова функции выше:
 

Скрытый текст
function CRandomTask:init_task_dialog(dlg, parent)
	local phr = dlg:AddPhrase("tm_seek_new_job","0","",-10000)
	local phrase_script = phr:GetPhraseScript()

	phr = dlg:AddPhrase("tm_"..parent.."_list_job","1","0",-10000)
	phrase_script = phr:GetPhraseScript()
	phrase_script:AddAction("task_manager.action_task_show")
	phrase_script:AddPrecondition("task_manager.precondition_vendor_can_task")
		
	phr = dlg:AddPhrase("tm_"..parent.."_has_no_job","2","0",-10000)
	phrase_script = phr:GetPhraseScript()
	phrase_script:AddPrecondition("task_manager.precondition_vendor_cannot_task")
	
	for k,v in pairs(self.task_id_by_parent[parent]) do
		phr = dlg:AddPhrase(self.task_info[v].name, tostring(self.task_info[v].init_phrase_id), "1", -10000)		
		phrase_script = phr:GetPhraseScript()
		phrase_script:AddPrecondition("task_manager.precondition_task_avail")

		phr = dlg:AddPhrase(self.task_info[v].text, tostring(self.task_info[v].desc_phrase_id), tostring(self.task_info[v].init_phrase_id), -10000)
		phrase_script = phr:GetPhraseScript()
		phrase_script:AddAction("task_manager.action_task_show_reward")
		
		phr = dlg:AddPhrase("tm_seek_job_yes", tostring(self.task_info[v].yes_phrase_id), tostring(self.task_info[v].desc_phrase_id), -10000)
		phrase_script = phr:GetPhraseScript()
		phrase_script:AddAction("task_manager.action_give_task") --добавил данное действие для вызова функции выше

		phr = dlg:AddPhrase("tm_seek_job_no", tostring(self.task_info[v].no_phrase_id), tostring(self.task_info[v].desc_phrase_id), -10000)
	end

	dlg:AddPhrase("tm_seek_job_abandon","3","1",-10000)
end
--
--
--
function action_task_show_reward(npc, actor)
	get_random_task():action_task_show_reward(npc, actor)
end

 

 

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

Если я правильно понял, это значение task_info.id.complex_type, которое для цикличек выглядит как type_parent.

 

Пример:

id = barmen_kill_stalker_5

complex_type = kill_stalker_barman

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

Шпаргалка

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

@Norman Eisenherz ну мне конкретно нужен этот id. Именно получить его, чтобы я мог прописать

local id = что-то, и чтобы это "что-то" выдало мне мой id квеста (в частном случае "tm_monster_part_1"), чтобы я потом прописал

local task_desc = self.task_info[id]

И уже от этого плясал и везде были свои данные конкретно этого квеста

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

1. В обработчик action по умолчанию передается 4 аргумента: speaker1, speaker2, dialog_id, phrase_id (obj, obj, str, str) – последнее значение для фразы с описанием будет равно desc_phrase_id.
2. Порядковые номера фраз в CRandomTask:__init() генерируются подряд: yes_phrase_id = desc_phrase_id +1.
3. Есть готовая таблица self.task_id_by_yes_phrase_id – из нее и получить id.

  • Полезно 2

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

Шпаргалка

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

Есть готовая таблица self.task_id_by_yes_phrase_id – из нее и получить id.

Ну таблица и эта, и task_id_by_init_phrase_id возвращали мне nil, хотя я вроде правильно всё подставлял, пришлось добавить цикл на прогон всех тасков персонажа и проверять совпадение по self.task_info[v].yes_phrase_id, но всё работает. Благодарю, что направил в нужное русло:drinks:

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

Проверил таблицу: данные точно заполняются, причем ключи phrase_id, как и в обработчике action, являются текстом – не было ли при сверке перевода в число?

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

Шпаргалка

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

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

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

AddAction + yes_phrase_id + task_id аналогично тому, что описано выше, если это циклический квест.

 

Edit: даже проще – если заголовок конфига известен заранее, достаточно добавить в тот же CRandomTask:init_task_dialog проверку

if v.name == "tm_find_artefact_1" then … yes_phrase:AddAction(…)

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

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

Шпаргалка

Ссылка на комментарий
07.09.2024 в 00:20, Norman Eisenherz сказал:

if v.name == "tm_find_artefact_1" then … yes_phrase:AddAction(…)

А можно на конкретном примере? А то я застрял в хитросплетениях строк уже.

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

 

--' Создается диалог актера, в котором будут выдаваться задания.
function CRandomTask:init_task_dialog(dlg, parent)
    local phr = dlg:AddPhrase("tm_seek_new_job","0","",-10000)
    local phrase_script = phr:GetPhraseScript()

    phr = dlg:AddPhrase("tm_"..parent.."_list_job","1","0",-10000)
    phrase_script = phr:GetPhraseScript()
    phrase_script:AddAction("task_manager.action_task_show")
    phrase_script:AddPrecondition("task_manager.precondition_vendor_can_task")

    phr = dlg:AddPhrase("tm_"..parent.."_has_no_job","2","0",-10000)
    phrase_script = phr:GetPhraseScript()
    phrase_script:AddPrecondition("task_manager.precondition_vendor_cannot_task")

    for k,v in pairs(self.task_id_by_parent[parent]) do
        phr = dlg:AddPhrase(self.task_info[v].name, tostring(self.task_info[v].init_phrase_id), "1", -10000)
        phrase_script = phr:GetPhraseScript()
        phrase_script:AddPrecondition("task_manager.precondition_task_avail")

        phr = dlg:AddPhrase(self.task_info[v].text, tostring(self.task_info[v].desc_phrase_id), tostring(self.task_info[v].init_phrase_id), -10000)
        phr = dlg:AddPhrase("tm_seek_job_yes", tostring(self.task_info[v].yes_phrase_id), tostring(self.task_info[v].desc_phrase_id), -10000)
        phrase_script = phr:GetPhraseScript()
        phrase_script:AddAction("task_manager.action_give_task")

        phr = dlg:AddPhrase("tm_seek_job_no", tostring(self.task_info[v].no_phrase_id), tostring(self.task_info[v].desc_phrase_id), -10000)
    end

        if v.name == "barmen_find_artefact_7" then

- тут я так пони, нужно строку с передачей предмета втулить как-то? Сообщение о передаче автоматом выдастся?

    end

    dlg:AddPhrase("tm_seek_job_abandon","3","1",-10000)
end

 

 

Уже разобрался. Пост под снос.

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

1. Надо привязаться к yes_phrase; действие "give_task" уже ссылается на нее – свое действие с проверкой ставить рядом.

2. Сообщение выдается при передаче предметов через обертку dialogs.relocate_item_section(…), которая ссылается на news_manager.script.

  • Полезно 1

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

Шпаргалка

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

@ARTLantist ,

вот готовая функция показа награды из АМК 1.4.1, может, поможет:

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

function show_reward(actor,npc,p1,p2)
    local reward_text, reward_money, task_details

    if random_task == nil then
        random_task = task_manager.CRandomTask()
    end

    task_details = random_task.task_info[random_task.task_id_by_init_phrase_id[p2-1]]

    if task_details == nil then return end

    reward_text = format_reward_text(task_details.reward_item)
    reward_money = task_details.reward_money

    local task_texture, task_rect = get_texture_info("ui_iconsTotal_find_item")
    if reward_text ~= nil and reward_text ~= "" then
        db.actor:give_talk_message("Я тебе за это дам вот что:", "ui\\ui_iconstotal", Frect():set(0,0,10,10), "simple_answer_item")
        db.actor:give_talk_message(reward_text, task_texture, task_rect,"iconed_trade_info")
    end

    if reward_money ~= nil then
        task_texture, task_rect = get_texture_info("ui_iconsTotal_found_money")
        if task_details.need_return and reward_text == "" then
            db.actor:give_talk_message(reward_money .. " RU (" .. game.translate_string("return_for_reward") .. ")", task_texture, task_rect, "iconed_trade_info")
        else
            db.actor:give_talk_message(reward_money .. " RU", task_texture, task_rect,"iconed_trade_info")
        end
    end
end

function format_reward_text(reward_list)
    local i,v, ii, vv
    local rwd = {}
    local reward_text = ""
    if reward_list == nil then return "" end
    for i,v in pairs(reward_list) do
        if rwd[v] == nil then
            rwd[v] = 1
        else
            rwd[v] = rwd[v] + 1
        end
    end
    for i,v in pairs(rwd) do
        if v == 1 then
            reward_text = reward_text .. game.translate_string(news_manager.get_inv_name(i)) .. ", "
        else
            reward_text = reward_text .. string.format("%s",v) .. "x " .. game.translate_string(news_manager.get_inv_name(i)) .. ", "
        end
    end
    if string.len(reward_text) >=2 then
        reward_text = string.sub (reward_text, 1, string.len(reward_text)-2)
    end
    return reward_text
end

 

А, вижу, уже разобрался.

Столкнулся с двумя проблемами в файле task_manager.

1) Отображение награды за квест. Суть: в скрипте АМК используется сбор информации о квесте вида:

    task_details = random_task.task_info[random_task.task_id_by_init_phrase_id[p2-1]]

    if task_details == nil then return end

    reward_text = format_reward_text(task_details.reward_item)
    reward_money = task_details.reward_money

 

У меня сильно видоизменённый скрипт из R.M.A., в котором данный метод не работает, судя по тому, что текст награды банально не отображается...

 

2) Награда инфой (инфопоршнем) за квест. Та же проблема в разных методах...

 

Вот весь скрипт с комментариями, что и где не работает:

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

--добавлен фикс от naxac, увеличивающий хранилище актора и предотвращающий вылеты при большом количестве заданий в PDA
local random_task = nil

local parent_by_story = {
    [003] = "trader",
    [500] = "barman",
    [902] = "ecolog",
    [507] = "dolg",
    [707] = "freedom",
    [006] = "wolf",
    [088] = "shustriy",
    [510] = "drunk_dolg",
    [504] = "hunter",
    [518] = "zastava_commander",
    [506] = "petrenko",
    [607] = "lisiy",
    [515] = "mercenary",
    [835] = "pri_trader"
}

local story_by_parent = {}
for sid, name in pairs(parent_by_story) do
    story_by_parent[name] = sid
end

local icon_task_by_type = {
    eliminate_lager = "ui_iconsTotal_eliminate_lager",
    eliminate_lair  = "ui_iconsTotal_mutant",
    defend_lager    = "ui_iconsTotal_defend_lager",
    kill_stalker    = "ui_iconsTotal_kill_stalker",
    artefact        = "ui_iconsTotal_artefact",
    monster_part    = "ui_iconsTotal_monster_part",
    find_info       = "ui_iconsTotal_find_info",
    find_item       = "ui_iconsTotal_find_item",
    find_device     = "ui_iconsTotal_find_device"
}

local return_task_by_type = {
    eliminate_lager = "return_for_reward",
    eliminate_lair  = "return_for_reward",
    defend_lager    = "return_for_reward",
    kill_stalker    = "return_for_reward",
    artefact        = "return_for_reward_bring",
    monster_part    = "return_for_reward_bring",
    find_info       = "return_for_reward",
    find_item       = "return_for_reward_bring",
    find_device     = "return_for_reward_bring"
}

local hash_to_id = {}
local id_to_hash = {}
-- хэш функция для строки (посмотреть литературу, на предмет оптимальной)
function stringhash(str)
    local mpl = 1
    local hash = 0
    for i = 1, string.len(str), 1 do
        local val = string.byte( string.sub(str,i,i) )
        hash = hash+mpl*val
        mpl = mpl*2
        if mpl == 512 then mpl = 1 end
    end
    return bit_and(hash, 65535)
end

class "CRandomTask"
function CRandomTask:__init()
    --' На конструкторе вычитываем LTX и создаем заготовки квестов.
    self.task_ini = ini_file("misc\\task_manager.ltx")
    self.task_phrase_id = 100

    --' Итерируемся по всем настройкам фраз
    if not self.task_ini:section_exist("list") then
        abort("There is no section

  • in task_manager.ltx")
        end
        local n = self.task_ini:line_count("list")
        local id, value = "",""
        local category = ""

    --' начальная установка
    self.task_info = {}

    for i=0,n-1 do
        result, id, value = self.task_ini:r_line("list",i,"","")

        local hash = stringhash(id)
        if hash_to_id[hash] then
            abort("Collision! Hash:%d id1:%s id2:%s", hash, hash_to_id[hash], id)
        end
        hash_to_id[hash] = id
        id_to_hash[id] = hash

        if not self.task_ini:section_exist(id) then
            abort("There is no section [%s] in task_manager.ltx", id)
        end

        self.task_info[tostring(id)]        = {}
        local curr_task_info            = self.task_info[tostring(id)]

        if not self.task_ini:line_exist(id, "type") then
            abort("Task manager error: no type in section [%s]", id)
        end

        curr_task_info.type            = self.task_ini:r_string(id, "type")

        curr_task_info.name            = id
        if self.task_ini:line_exist(id, "parent") then
            curr_task_info.parent        = self.task_ini:r_string(id, "parent")
            curr_task_info.complex_type = curr_task_info.type .. "_" .. curr_task_info.parent
        else
            curr_task_info.parent        = "nil"
            curr_task_info.complex_type = curr_task_info.type
        end

        if self.task_ini:line_exist(id, "target") then
            curr_task_info.target        = self.task_ini:r_string(id, "target")
        end

        if self.task_ini:line_exist(id, "target_info") then
            curr_task_info.target_info    = self.task_ini:r_string(id, "target_info")
        end

        if self.task_ini:line_exist(id, "text") then
            curr_task_info.text        = self.task_ini:r_string(id, "text")
        end
        if self.task_ini:line_exist(id, "description") then
            curr_task_info.description    = self.task_ini:r_string(id, "description")
        end

        curr_task_info.time            = utils.cfg_get_number(self.task_ini, id, "time", nil, false)
        curr_task_info.idle_time        = utils.cfg_get_number(self.task_ini, id, "idle_time", nil, false, 24*60*60) --' Время между выдачами задания (в игровых секундах)
        curr_task_info.prior            = utils.cfg_get_number(self.task_ini, id, "prior", nil, false, 0) --' Приоритет квеста, выдаются доступные квесты с наименьшим приоритетом

        -- Выдаём инфопоршни или запускаем сторонние функции при взятии задания (lsclon)
        if self.task_ini:line_exist(id, "give_info") then
                curr_task_info.info_give = xr_logic.parse_condlist(db.actor, "task_manager", "give_info", self.task_ini:r_string(id, "give_info"))
        end

        if self.task_ini:line_exist(id, "init_condition") then
            curr_task_info.init_condition = xr_logic.parse_condlist(db.actor, "task_manager", "init_condition", self.task_ini:r_string(id, "init_condition"))
        end

        if self.task_ini:line_exist(id, "reward_item") then
            curr_task_info.reward_item = se_respawn.parse_names(
                self.task_ini:r_string(id, "reward_item")
            )
        end

        if self.task_ini:line_exist(id, "reward_money") then
            curr_task_info.reward_money = self.task_ini:r_u32(id, "reward_money")
        end

        -- Награда информацией
                --три строки ниже переделаны под методы данного скрипта и по идее, рабочие
        --if self.task_ini:line_exist(id, "reward_info") then
            --curr_task_info.reward_info = xr_logic.parse_condlist(db.actor, "task_manager", "reward_info", self.task_ini:r_string(id, "reward_info"))
        --end

                --закоменченное ниже не работало
        --local reward_info = utils.cfg_get_string(self.task_ini, id, "reward_info", nil, false,"")
        --if reward_info =="" then reward_info = nil end
        --self.task_info[id].reward_info = reward_info
        --if reward_info then
        --self:read_info_reward_section(self.task_ini,reward_info,self.task_info[id])
        --end

        -- Диалог для квестовой жертвы
        --self.task_info[id].target_dialog=utils.cfg_get_string(self.task_ini, id, "target_dialog", nil, false,"")

                -- всё равно не используется
        -- if self.task_ini:line_exist(id, "community") then
            -- curr_task_info.community = self.task_ini:r_string(id, "community")
        -- end

        curr_task_info.reward_rank        = utils.cfg_get_number(self.task_ini, id, "reward_rank", nil, false, 0)
        curr_task_info.reward_reputation    = utils.cfg_get_number(self.task_ini, id, "reward_reputation", nil, false)
        curr_task_info.reward_relation        = parse_key_value(utils.cfg_get_string(self.task_ini, id, "reward_relation", nil, false, ""))

        if self.task_ini:line_exist(id, "condlist") then
            curr_task_info.condlist        = xr_logic.parse_condlist(db.actor, "task_manager", "condlist", self.task_ini:r_string(id, "condlist"))
        else
            curr_task_info.condlist        = xr_logic.parse_condlist(db.actor, "task_manager", "condlist", "true")
        end

        curr_task_info.need_return        = utils.cfg_get_bool(self.task_ini, id, "need_return", nil, false, true)

        curr_task_info.init_phrase_id        = self:gen_phrase_id()
        curr_task_info.desc_phrase_id        = self:gen_phrase_id()
        curr_task_info.yes_phrase_id        = self:gen_phrase_id()
        curr_task_info.no_phrase_id        = self:gen_phrase_id()

        --' По умолчанию квест доступен для выдачи
        curr_task_info.enabled            = true
        --' Доступен ли квест по своим свойствам. По умолчанию всегда недоступен.
        --' Этот параметр зависит от наличия целей для квестов и того срабатывает ли прекондишн квеста
        curr_task_info.enabled_props        = false

        --' Статус квеста, может быть: "normal", "selected", "completed", "refused", "failed", "rewarded"
        curr_task_info.status = "normal"
    end

    --' Создание дополнительных ассоциативных таблиц для облегчения поиска
    self.task_id_by_type = {}
    self.task_id_by_parent = {}
    self.task_id_by_yes_phrase_id = {}
    self.task_id_by_init_phrase_id = {}
    self.active_task_by_type = {}
    self.task_id_self_inited = {}
    for k,v in pairs(self.task_info) do
        --' По типу квеста
        if self.task_id_by_type[v.type] == nil then
            self.task_id_by_type[v.type] = {}
        end
        table.insert(self.task_id_by_type[v.type], k)

        --' По типу вендора
        if self.task_id_by_parent[v.parent] == nil then
            self.task_id_by_parent[v.parent] = {}
        end
        table.insert(self.task_id_by_parent[v.parent], k)

        --' По id фразы согласия на квест
        self.task_id_by_yes_phrase_id[tostring(v.yes_phrase_id)] = k
        --' По id фразы выдачи квеста.
        self.task_id_by_init_phrase_id[tostring(v.init_phrase_id)] = k
        --' По самовыдаваемости
        if v.init_condition ~= nil then
            table.insert(self.task_id_self_inited, k)
        end
    end
end

--------- Награда информацией --------
--function CRandomTask:read_info_reward_section(ini,sect,container)
                --строка ниже переделана под данный скрипт и в теории рабочая
        --container.reward_info_portion = xr_logic.parse_condlist(db.actor, "task_manager", "reward_info", self.task_ini:r_string(id, "reward_info"))
                --строка ниже не работает, метод utils.cfg_get_string не используется в данном скрипте так
        container.reward_info_portion = utils.cfg_get_string(ini,sect,"info_portion",nil,true,"")
                --всё, что ниже, по идее, нужно переделать...
        --container.reward_info_dialog ={}
        --local phr = 1
        --while true do
        --local phrase_id = utils.cfg_get_string(ini,sect,"phrase_"..phr,nil,false,"")
        --phr = phr+1
        --if phrase_id == nil or phrase_id =="" then break end
        --table.insert(container.reward_info_dialog,phrase_id)
        --end
--end
--------------------------------------
--' Сохранение
--' Статус квеста, может быть: "normal", "selected", "completed", "refused", "failed", "rewarded"
-- Ну и замечательно. Запишем его числом. - семикратная экономия.
local status_to_num = {
    ["normal"]    = 0,
    ["selected"]    = 1,
    ["completed"]    = 2,
    ["refused"]    = 3,
    ["failed"]    = 4,
    ["rewarded"]    = 5
}
local num_to_status={}
for k, v in pairs(status_to_num) do
    num_to_status[v] = k
end

-- Будем записывать не id задания, а его хеш - семикратная экономия.
function CRandomTask:save(p)
    --' Считаем количество записей
    local i = 0
    for _ in pairs(self.task_info) do
        i = i + 1
    end
    p:w_u16(i)

    for k, v in pairs(self.task_info) do
        if not id_to_hash[k] then
            abort("[CRandomTask:save] Cannot find hash for id %s!", k)
        end
        p:w_u16(id_to_hash[k])

        i = status_to_num[v.status] or abort("[CRandomTask:save] Wrong status '%s' for task %s!", v.status, k)

        if v.enabled then i = bit_or(i, 8) end
        if v.enabled_props then i = bit_or(i, 16) end

        -- selected_target и defend_target сохраняем только если они есть
        -- активен ли таск - сохраняем тут же одним битом
        -- хрен-знает-сколькикратная экономия
        if v.selected_target then i = bit_or(i, 32) end
        if v.defend_target then i = bit_or(i, 64) end
        if self.active_task_by_type[v.complex_type] == k then
            i = bit_or(i, 128)
        end

        p:w_u8(i)

        if v.selected_target then
            p:w_u16(v.selected_target)        -- id, u16
        end
        if v.defend_target then
            p:w_u32(v.defend_target)        -- story_id, u32
        end

        utils.w_CTime(p, v.last_task_time)
    end
end
--' Загрузка
function CRandomTask:load(p)
    --' Считаем количество записей
    local i = p:r_u16()
    local n, id, hash
    for k = 1, i do
        hash = p:r_u16()
        id = hash_to_id[hash] or abort("[CRandomTask:load] Cannot find id for hash %d!", hash)
        local t = self.task_info[id] or abort("[CRandomTask:load] Cannot find task for id %s!", id)
        n = p:r_u8()
        t.enabled = bit_and(n, 8)~=0
        t.enabled_props = bit_and(n, 16)~=0

        if bit_and(n, 32) ~= 0 then
            t.selected_target = p:r_u16()
        end
        if bit_and(n, 64) ~= 0 then
            t.defend_target = p:r_u32()
        end
        if bit_and(n, 128) ~= 0 then
            if self.active_task_by_type[t.complex_type] ~= nil then
                abort("[CRandomTask:load] Error with load active task[%s]: task with type '%s' already loaded: %s",
                    id, t.complex_type, self.active_task_by_type[t.complex_type])
            end
            self.active_task_by_type[t.complex_type] = id
        end

        n = bit_and( n, bit_not(8+16+32+64+128) )
        t.status = num_to_status[n] or abort("[CRandomTask:load] Error with loading task [%s] status: %s", id, n)

        t.last_task_time = utils.r_CTime(p)
    end
end

--' Генератор уникальных ID для фраз
function CRandomTask:gen_phrase_id()
    self.task_phrase_id = self.task_phrase_id + 1
    return tostring(self.task_phrase_id)
end

--' Возвращает идентификатор вендора, с которым мы говорим
function CRandomTask:get_parent(npc)
    local story_id = npc:story_id()
    if parent_by_story[story_id] == nil then
        abort("Task manager error: wrong parent story_id[%s]", story_id)
    end
    return parent_by_story[story_id]
end

--' Может ли вендор выдать квест
function CRandomTask:parent_can_task(actor, npc, p1, p2, p3)
    local parent = self:get_parent(npc)
    local avail = false
    --local task_limit = 0
    self:task_avail(actor, npc, nil, nil, nil, "reset")
    for k,v in pairs(self.task_id_by_parent[parent]) do
        if self:task_avail(actor, npc, nil, nil, self.task_info[v].init_phrase_id, true) then
            avail = true
        end
    end
    -- Ограничение максимального количества (task_limit) второстепенных квестов, lvg_brest
    --[[for k,v in pairs(self.active_task_by_type) do
        if self.task_info[v].status == "selected" or self.task_info[v].status == "completed" then
            task_limit = task_limit + 1
        end
    end
    if task_limit >= 8 then avail = false end]]
    return avail
end

--' Есть ли у игрока хоть одно задание от данного вендора
function CRandomTask:active_parent_task(actor, npc)
    local parent = self:get_parent(npc)
    for k,v in pairs(self.active_task_by_type) do

        if self.task_info[v].parent == parent and
          (self.task_info[v].status == "selected" or
           self.task_info[v].status == "completed")
        then
            return true
        end
    end
    return false
end

--' Есть ли игрока завершённые задания (которые осталось только сдать)
function CRandomTask:have_completed_job(actor, npc)
    local parent = self:get_parent(npc)
    for k,v in pairs(self.active_task_by_type) do
        if self.task_info[v].parent == parent and
           self.task_info[v].status == "completed"
        then
            return true
        end
    end
    return false
end

--' Выдача квеста игроку
function CRandomTask:action_give_task(actor, npc, p1, p2)
    local task = CGameTask()

    local task_desc = self.task_info[self.task_id_by_yes_phrase_id[p2]]

    task:load(task_desc.complex_type)
    task:set_title(task_desc.type)

    local oo = task:get_objective(0)
    oo:set_article_id(task_desc.description)

    local objective = SGameTaskObjective(task,1)
    objective:set_description(task_desc.name)
    --' Выбираем текущую цель квеста
    if task_desc.target_objects ~= nil then
        self.task_info[self.task_id_by_yes_phrase_id[p2]].selected_target = task_desc.target_objects[math.random(table.getn(task_desc.target_objects))]
    end

    --local mob_lagers = {"esc_bridge_boar","esc2_dogs_lair","esc_flesh_2","gar_smart_monster_lair2","gar_nest_flesh","gar_dogs_lair_1","val_smart_bloodsucker_lair_2","val_snork_lair_1","bar_zastava_dogs_lair","ros_smart_monster1","ros_smart_monster2","ros_smart_monster5","yan_smart_controler1","yantar2_snork_small4","yan_tonnel_snorks","mil_hunters_bloodsucker","mil_lair2","mil_lair3","mil_village_lair","pri_smart_snork_lair2","pri_smart_pseudodog_lair1","pri_smart_giant_lair1"}

    if task_desc.type == "eliminate_lager" then
        objective:set_map_hint(task_desc.text)
        objective:set_map_location("eliminate_lager_location")
        --[[for i=1, #mob_lagers, 1 do
            if task_desc.target == mob_lagers then
                objective:set_map_location("eliminate_lair_location")
                break
            else
                objective:set_map_location("eliminate_lager_location")
            end
        end]]
        objective:set_object_id(task_desc.selected_target)
    elseif task_desc.type == "eliminate_lair" then
        objective:set_map_hint(task_desc.text)
        objective:set_map_location("eliminate_lair_location")
        objective:set_object_id(task_desc.selected_target)
    elseif task_desc.type == "defend_lager" then
        objective:set_map_hint(task_desc.text)
        objective:set_map_location("defend_lager_location")
        objective:set_object_id(task_desc.selected_target)

        local defend_object = alife():object(task_desc.selected_target)
        local sm_ini = defend_object:spawn_ini()
        self.task_info[self.task_id_by_yes_phrase_id[p2]].defend_target = utils.cfg_get_number(sm_ini, "random_task", "defend_target", nil, true)
    elseif task_desc.type == "kill_stalker" then
        objective:set_map_hint(task_desc.text)
        objective:set_map_location("kill_stalker_location")
        objective:set_object_id(task_desc.selected_target)
    elseif task_desc.type == "find_item" then
        objective:set_map_hint(task_desc.text)
        objective:set_map_location("find_item_location")
        objective:set_object_id(task_desc.selected_target)
    end
    objective:add_complete_func("task_manager.task_complete")
    task:add_objective(objective)

    if task_desc.need_return then
        objective = SGameTaskObjective(task,2)
        objective:set_description(return_task_by_type[task_desc.type])

        objective:set_map_hint(return_task_by_type[task_desc.type])
        objective:set_map_location("blue_location")
        objective:set_object_id(alife():story_object(tonumber(story_by_parent[task_desc.parent])).id)
        task:add_objective(objective)
    end

    -- Выдаём инфопоршни или запускаем сторонние функции при взятии задания (lsclon)
    if task_desc.info_give then
        xr_logic.pick_section_from_condlist(db.actor, db.actor, task_desc.info_give)
    end

    local time = 0
    if task_desc.time ~= nil then
        time = task_desc.time * 1000
    end
    db.actor:give_task(task,time,false)

    --' дизаблим все остальные задания данного типа, так как игрок не может одновременно обладать двумя заданиями одного типа.
    self.task_info[self.task_id_by_yes_phrase_id[p2]].status = "selected"
    self.active_task_by_type[task_desc.complex_type] = self.task_id_by_yes_phrase_id[p2]
    for k,v in pairs(self.task_info) do
        if v.complex_type == task_desc.complex_type then
            v.enabled = false
        end
    end
end

--' Отказ игроком от квеста
function CRandomTask:action_refuse_task(actor, npc, p1, p2)
    local task_desc = self.task_info[self.task_id_by_yes_phrase_id[p2]]

    --' Делаем доступными все задания данного типа
    self.task_info[self.task_id_by_yes_phrase_id[p2]].status = "refused"
    self.task_info[self.active_task_by_type[task_desc.complex_type]].selected_target = nil
    for k,v in pairs(self.task_info) do
        if v.complex_type == task_desc.complex_type then
            v.enabled = true
        end
    end
end

--' Проверяем, не выполнен ли таск
function CRandomTask:task_complete(p1, p2)
    if db.actor == nil then
        return false
    end

    local sel_task = self.task_info[self.active_task_by_type[p1]]
    if sel_task == nil then
        abort("WRONG RANDOM TASK %s %s", tostring(p1), tostring(p2))
    end

    if p2 == 0 then
        if not sel_task.need_return and sel_task.status == "completed" then
            self.task_info[self.active_task_by_type[p1]].last_task_time = game.get_game_time()
            return true
        end
        if sel_task.status == "rewarded" then
            self.task_info[self.active_task_by_type[p1]].last_task_time = game.get_game_time()
            return true
        end
    end

    if p2 == 1 then
        if string.find(p1, "eliminate_lager") ~= nil then
            local oo = alife():object(sel_task.selected_target)
            if oo and oo.gulag:get_population_comed() == 0 then
                self.task_info[self.active_task_by_type[p1]].status = "completed"
                return true
            end
        elseif string.find(p1, "eliminate_lair") ~= nil then
            local oo = alife():object(sel_task.selected_target)
            if oo and oo.gulag:get_population_comed() == 0 then
                self.task_info[self.active_task_by_type[p1]].status = "completed"
                return true
            end
        elseif string.find(p1, "defend_lager") ~= nil then
            --' Квест выполнен потому что рейд прекратился
            if xr_gulag.getGulagState(sel_task.defend_target) == 0 then
                self.task_info[self.active_task_by_type[p1]].status = "completed"
                return true
            end
        elseif string.find(p1, "kill_stalker") ~= nil then
            local oo = alife():object(sel_task.selected_target)

            --' Проверка бага
            if oo == nil then
                abort("OBJ = nil for task %s", tostring(self.active_task_by_type[p1]))
            elseif oo.alive == nil then
                abort("OBJ.NAME = %s", obj:name())
            end

            if oo and oo:alive() == false then
                self.task_info[self.active_task_by_type[p1]].status = "completed"
                return true
            end
        elseif string.find(p1, "artefact") ~= nil then
            if db.actor:object(sel_task.target) ~= nil then
                self.task_info[self.active_task_by_type[p1]].status = "completed"
                return true
            end
        elseif string.find(p1, "monster_part") ~= nil then
            if db.actor:object(sel_task.target) ~= nil then
                self.task_info[self.active_task_by_type[p1]].status = "completed"
                return true
            end
        elseif string.find(p1, "find_item") ~= nil then
            if db.actor:object(sel_task.target) ~= nil then
                self.task_info[self.active_task_by_type[p1]].status = "completed"
                return true
            end
        elseif string.find(p1, "find_device") ~= nil then
            if db.actor:object(sel_task.target) ~= nil then
                self.task_info[self.active_task_by_type[p1]].status = "completed"
                return true
            end
        elseif string.find(p1, "find_info") ~= nil then
            if has_alife_info(sel_task.target_info) then
                self.task_info[self.active_task_by_type[p1]].status = "completed"
                return true
            end
        end
    end

    return false
end

--' Проверяем, не профейлен ли таск
function CRandomTask:task_fail(p1, p2)
    if p2 == 0 then
        local sel_task = self.task_info[self.active_task_by_type[p1]]

        if sel_task == nil then
            abort("WRONG RANDOM TASK %s %s", tostring(p1), tostring(p2))
        end

        --' Проверяем что жив, выдавший квест.
        local parent = alife():story_object(story_by_parent[sel_task.parent])
        if parent == nil or (parent.alive ~= nil and not parent:alive()) then
            self.task_info[self.active_task_by_type[p1]].status = "failed"
            self.task_info[self.active_task_by_type[p1]].last_task_time = game.get_game_time()
            return true
        end

        if sel_task.status == "refused" or sel_task.status == "failed" then
            self.task_info[self.active_task_by_type[p1]].last_task_time = game.get_game_time()
            return true
        end
        if string.find(p1, "defend_lager") ~= nil then
            if alife():object(sel_task.selected_target).gulag:get_population_comed() == 0 then
                self.task_info[self.active_task_by_type[p1]].status = "failed"
                self.task_info[self.active_task_by_type[p1]].last_task_time = game.get_game_time()
                return true
            end
        end
    end
    return false
end
--' Обнуление переменных при завершении или провале таска
function CRandomTask:task_callback(p1, p2, state)
    if p2 ~= 0 then
        return
    end

    if self.active_task_by_type[p1] == nil then
        return
    end

    if state == task.completed then
        self.task_info[self.active_task_by_type[p1]].status = "normal"
        --' восстановление других заданий данного типа
        for k,v in pairs(self.task_info) do
            if v.complex_type == self.task_info[self.active_task_by_type[p1]].complex_type then
                v.enabled = true
            end
        end
        self.active_task_by_type[p1] = nil

    elseif state == task.fail then
        self.task_info[self.active_task_by_type[p1]].status = "normal"

        --' восстановление других заданий данного типа
        for k,v in pairs(self.task_info) do
            if v.complex_type == self.task_info[self.active_task_by_type[p1]].complex_type then
                v.enabled = true
            end
        end
        self.active_task_by_type[p1] = nil
    end
end
--' Выводит список доступных квестов
function CRandomTask:action_task_show(npc, actor)
    local parent = self:get_parent(npc)
    for k,v in pairs(self.task_id_by_parent[parent]) do
        if self:task_avail(actor, npc, nil, nil, self.task_info[v].init_phrase_id, false) then
            local task_texture, task_rect = get_texture_info(icon_task_by_type[self.task_info[v].type])
            db.actor:give_talk_message("%c[230,255,128,64]"..game.translate_string(self.task_info[v].name).."\\n"..game.translate_string("st_task_time").." "..self:transform_number_to_date(self.task_info[v].time), task_texture, task_rect,"iconed_trade_info")
        end
    end
end
--' Ray Twitty aka Shadows: преобразование числа в дату сдачи таска
function CRandomTask:transform_number_to_date(time)
    if time ~= nil then
        local d, h, m = time / 86400, time / 3600, time / 60
        if d >= 1 then
            return math.ceil(d).." "..game.translate_string("ui_st_days")
        elseif h >= 1 then
            return math.ceil(h).." "..game.translate_string("ui_st_hours")
        else
            return math.ceil(m).." "..game.translate_string("ui_st_mins")
        end
    end
    return game.translate_string("ui_st_indefinitely")
end
--' Проверка доступен ли текущий таск для выдачи
function CRandomTask:task_avail(actor, npc, p1, p2, p3, calculate)
    local task_desc = self.task_info[self.task_id_by_init_phrase_id[p3]]
    --' Если calculate == true то нужно проверять check_task_props, инача просто вернуть значения.
    if calculate == "reset" then
        self.current_parent_type_prior = {}
        return
    elseif calculate == true then
        self:check_task_props(self.task_id_by_init_phrase_id[p3])

        local t = task_desc.enabled and task_desc.enabled_props and task_desc.init_condition == nil

        --' Устанавливать обрезания по приоритетам тут.
        if t == true and (self.current_parent_type_prior[task_desc.complex_type] == nil or
           self.current_parent_type_prior[task_desc.complex_type] > task_desc.prior )
        then
            self.current_parent_type_prior[task_desc.complex_type] = task_desc.prior
        end

        return t
    end

    if self.current_parent_type_prior[task_desc.complex_type] ~= nil and
       self.current_parent_type_prior[task_desc.complex_type] < task_desc.prior then
        return false
    end

    return task_desc.enabled and
           task_desc.enabled_props and
           task_desc.init_condition == nil
end
--' Проверка свойств таска
function CRandomTask:check_task_props(task_id)
    --' Проверка по активным заданиям данного типа у вендора.
    if self.active_task_by_type[self.task_info[task_id].complex_type] ~= nil then
        self.task_info[task_id].enabled_props = false
        return
    end

    --' Проверка по кондлисту
    if xr_logic.pick_section_from_condlist(db.actor, db.actor, self.task_info[task_id].condlist) == nil then
        self.task_info[task_id].enabled_props = false
        return
    end

    --' Проверка по таймауту
    if self.task_info[task_id].last_task_time ~= nil and
        game.get_game_time():diffSec(self.task_info[task_id].last_task_time) < self.task_info[task_id].idle_time
    then
        self.task_info[task_id].enabled_props = false
        return
    end

    --' проверка по таргету
    if self.task_info[task_id].type == "eliminate_lager" then
        if self.task_info[task_id].target_objects == nil then
            self.task_info[task_id].enabled_props = false
            return
        end
        for k,v in pairs(self.task_info[task_id].target_objects) do
            local gulag = alife():object(v).gulag
            if gulag:get_population_comed() > 0 then
                self.task_info[task_id].enabled_props = true
                return
            end
        end
        self.task_info[task_id].enabled_props = false
        return
    elseif self.task_info[task_id].type == "eliminate_lair" then
        if self.task_info[task_id].target_objects == nil then
            self.task_info[task_id].enabled_props = false
            return
        end
        for k,v in pairs(self.task_info[task_id].target_objects) do
            local gulag = alife():object(v).gulag
            if gulag:get_population_comed() > 0 then
                self.task_info[task_id].enabled_props = true
                return
            end
        end
        self.task_info[task_id].enabled_props = false
        return
    elseif self.task_info[task_id].type == "defend_lager" then
        if self.task_info[task_id].target_objects == nil then
            self.task_info[task_id].enabled_props = false
            return
        end
        for k,v in pairs(self.task_info[task_id].target_objects) do
            local defend_object = alife():object(v)
            local sm_ini = defend_object:spawn_ini()
            local defend_target = utils.cfg_get_number(sm_ini, "random_task", "defend_target", nil, true)
            if xr_gulag.getGulagState(defend_target) == 1 then
                self.task_info[task_id].enabled_props = true
                return
            end
        end
        self.task_info[task_id].enabled_props = false
        return
    elseif self.task_info[task_id].type == "kill_stalker" then
        if self.task_info[task_id].target_objects == nil then
            self.task_info[task_id].enabled_props = false
            return
        end
        for k,v in pairs(self.task_info[task_id].target_objects) do
            local obj = alife():object(v)

            --' Проверка бага
            if obj ~= nil and obj.alive == nil then
                abort("OBJ.NAME = %s", obj:name())
            end

            if obj ~= nil and
               obj:alive() == true
            then
                self.task_info[task_id].enabled_props = true
                return
            else
                table.remove(self.task_info[task_id].target_objects, k)
            end
        end
        self.task_info[task_id].enabled_props = false
        return
    elseif self.task_info[task_id].type == "find_item" then
        if self.task_info[task_id].target_objects == nil or table.getn(self.task_info[task_id].target_objects) == 0 then
            self.task_info[task_id].enabled_props = false
            return
        end
        for k,v in pairs(self.task_info[task_id].target_objects) do
            local obj = alife():object(v)
            if obj ~= nil then
                --' Нужно игнорировать предметы, которые находяться у вендоров.
                if obj.parent_id ~= nil then
                    for kk,vv in pairs(parent_by_story) do
                        local parent = alife():story_object(kk)
                        if parent ~= nil and obj.parent_id == parent.id then
                            --' Игнорим предмет
                            self.task_info[task_id].enabled_props = false
                            return
                        end
                    end
                end

                self.task_info[task_id].enabled_props = true
                return
            end
            self.task_info[task_id].enabled_props = false
            return
        end
    else
        self.task_info[task_id].enabled_props = true
        return
    end
end
--' Проверяем можем ли мы сейчас выдать какой либо самоинициализующийся таск
function CRandomTask:actor_update()
    for k,v in pairs(self.task_id_self_inited) do
        if self.task_info[v].status == "normal" then
            self:check_task_props(v)
            if self.task_info[v].enabled_props == true and
               self.task_info[v].enabled == true and
               xr_logic.pick_section_from_condlist(db.actor, db.actor, self.task_info[v].init_condition) ~= nil
            then
                --' Нужно автоматически выдать квест
                self:action_give_task(db.actor, nil, nil, self.task_info[v].yes_phrase_id)
            end
        end
    end
end
--' Функция для аварийной зачистки - убирает у неактивных квестов дату последнего обращения, список объектов и текущий объект,
--' в результате чего позволяет освободить довольно приличное количество места в хранилище ГГ, KamikaZze
function CRandomTask:cleanup_actor()
        for k,v in pairs(self.task_info) do
            if v.status == "normal" then
                if v.type == "eliminate_lager" or
                v.type == "eliminate_lair" or
                v.type == "defend_lager" or
                v.type == "kill_stalker" or
                v.type == "artefact" or
                v.type == "find_item" or
                v.type == "find_device" or
                v.type == "monster_part" or
                v.type == "storyline" then
                    v.last_task_time = nil
                    v.selected_target = nil
                    v.target_objects = nil
                end
            end
        end
end
--' Проверяется является ли текущий таск выданным игроку
function CRandomTask:active_task(actor, npc, p1, p2, p3)
    return self.task_info[self.task_id_by_init_phrase_id[p3]].status == "selected"
end
--' Создается диалог актера, в котором будут выдаваться задания.
function CRandomTask:init_task_dialog(dlg, parent)
    local phr = dlg:AddPhrase("tm_seek_new_job","0","",-10000)
    local phrase_script = phr:GetPhraseScript()

    phr = dlg:AddPhrase("tm_"..parent.."_list_job","1","0",-10000)
    phrase_script = phr:GetPhraseScript()
    phrase_script:AddAction("task_manager.action_task_show")
    phrase_script:AddPrecondition("task_manager.precondition_vendor_can_task")

    phr = dlg:AddPhrase("tm_"..parent.."_has_no_job","2","0",-10000)
    phrase_script = phr:GetPhraseScript()
    phrase_script:AddPrecondition("task_manager.precondition_vendor_cannot_task")

    for k,v in pairs(self.task_id_by_parent[parent]) do
        phr = dlg:AddPhrase(self.task_info[v].name, tostring(self.task_info[v].init_phrase_id), "1", -10000)
        phrase_script = phr:GetPhraseScript()
        phrase_script:AddPrecondition("task_manager.precondition_task_avail")

                --три строки ниже должны работать
        phr = dlg:AddPhrase(self.task_info[v].text, tostring(self.task_info[v].desc_phrase_id), tostring(self.task_info[v].init_phrase_id), -10000)
        phrase_script = phr:GetPhraseScript()
        phrase_script:AddAction("task_manager.show_reward")

        phr = dlg:AddPhrase(self.task_info[v].text, tostring(self.task_info[v].desc_phrase_id), tostring(self.task_info[v].init_phrase_id), -10000)
        phr = dlg:AddPhrase("tm_seek_job_yes", tostring(self.task_info[v].yes_phrase_id), tostring(self.task_info[v].desc_phrase_id), -10000)
        phrase_script = phr:GetPhraseScript()
        phrase_script:AddAction("task_manager.action_give_task")

        phr = dlg:AddPhrase("tm_seek_job_no", tostring(self.task_info[v].no_phrase_id), tostring(self.task_info[v].desc_phrase_id), -10000)
    end

    dlg:AddPhrase("tm_seek_job_abandon","3","1",-10000)
end
--' Функция, в которой будет выдаваться вещевая награда за выполненные квесты
function CRandomTask:task_reward(npc, actor, p1, p2)
    local parent = self:get_parent(npc)
    for k,v in pairs(self.active_task_by_type) do
        local task_desc = self.task_info[v]
        if task_desc.status == "completed" and task_desc.parent == parent then
            --' Забираем у игрока квестовый предмет.
            local can_finish = true
            if task_desc.type == "artefact" then
                if db.actor:object(task_desc.target) == nil then
                    can_finish = false
                else
                    dialogs.relocate_item_section(npc, task_desc.target, "out")
                end
            elseif task_desc.type == "monster_part" then
                if db.actor:object(task_desc.target) == nil then
                    can_finish = false
                else
                    dialogs.relocate_item_section(npc, task_desc.target, "out")
                end
            elseif task_desc.type == "find_device" then
                if db.actor:object(task_desc.target) == nil then
                    can_finish = false
                else
                    dialogs.relocate_item_section(npc, task_desc.target, "out")
                end
            elseif task_desc.type == "find_item" then
                if db.actor:object(task_desc.target) == nil then
                    can_finish = false
                else
                    dialogs.relocate_item_section(npc, task_desc.target, "out")
                end
            end

            if can_finish == true then
                self.task_info[v].status = "rewarded"

                if task_desc.reward_money ~= nil then
                    dialogs.relocate_money(npc, task_desc.reward_money, "in")
                end

                if task_desc.reward_item ~= nil then
                    for kk,vv in pairs(task_desc.reward_item) do
                        dialogs.relocate_item_section(npc, vv, "in")
                    end
                end

                if task_desc.reward_reputation ~= nil then
                    db.actor:change_character_reputation(task_desc.reward_reputation)
                end

                if task_desc.reward_relation ~= nil then
                    for kk,vv in pairs(task_desc.reward_relation) do
                        relation_registry.change_community_goodwill (kk, db.actor:id(), tonumber(vv))
                    end
                end

                if task_desc.reward_rank ~= nil then
                    actor_stats.add_points("quests", task_desc.name, 1, task_desc.reward_rank)
                    db.actor:set_character_rank(db.actor:character_rank() + task_desc.reward_rank)
                end
            end
        end    
    end
end
--' Функция, в которой будет выдаваться вещевая награда за выполненные сторилайновые квесты
function CRandomTask:task_reward_storyline(task)
    local task_desc = self.task_info[task:get_id()]
    if task_desc == nil or task_desc.type ~= "storyline" then
        return
    end

    if task_desc.reward_reputation ~= nil then
        db.actor:change_character_reputation(task_desc.reward_reputation)
    end

    if task_desc.reward_relation ~= nil then
        for kk,vv in pairs(task_desc.reward_relation) do
            relation_registry.change_community_goodwill (kk, db.actor:id(), tonumber(vv))
        end
    end

    if task_desc.reward_rank ~= nil then
        actor_stats.add_points("quests", task_desc.name, 1, task_desc.reward_rank)
        db.actor:set_character_rank(db.actor:character_rank() + task_desc.reward_rank)
    end
end
--' Создается диалог актера, в котором будут приниматься задания
function CRandomTask:init_reward_dialog(dlg, parent)
    local phr = dlg:AddPhrase("tm_reward_job","0","",-10000)
    local phrase_script = phr:GetPhraseScript()

    phr = dlg:AddPhrase("tm_"..parent.."_job_complete", "1", "0", -10000)
    phrase_script = phr:GetPhraseScript()
    phrase_script:AddAction("task_manager.action_task_reward")
    phrase_script:AddPrecondition("task_manager.precondition_have_completed_job")

    phr = dlg:AddPhrase("tm_"..parent.."_job_ask", "2", "0", -10000)
    phrase_script = phr:GetPhraseScript()
    phrase_script:AddPrecondition("task_manager.precondition_dont_have_completed_job")

    -- Список возможных квестов трейдера.
    for k,v in pairs(self.task_id_by_parent[parent]) do
        phr = dlg:AddPhrase(self.task_info[v].name, tostring(self.task_info[v].init_phrase_id), "2", -10000)
        phrase_script = phr:GetPhraseScript()
        phrase_script:AddPrecondition("task_manager.precondition_active_task")

        phr = dlg:AddPhrase("tm_"..parent.."_job_what", tostring(self.task_info[v].desc_phrase_id), tostring(self.task_info[v].init_phrase_id), -10000)

        phr = dlg:AddPhrase("tm_job_refuse", tostring(self.task_info[v].yes_phrase_id), tostring(self.task_info[v].desc_phrase_id), -10000)
        phrase_script = phr:GetPhraseScript()
        phrase_script:AddAction("task_manager.action_refuse_task")

        phr = dlg:AddPhrase("tm_job_nothing", tostring(self.task_info[v].no_phrase_id), tostring(self.task_info[v].desc_phrase_id),-10000)

        --кусок закоменченного ниже нужно переделать
    --if self.task_info[v].reward_info then
    --local phrcnt = table.getn(self.task_info[v].reward_info_dialog)
    --if phrcnt == 0 then
        --phrase_script:AddGiveInfo(self.task_info[v].reward_info_portion)
        --phrase_script:AddAction("dialog_manager.info_received")
        --else
        -- Добавляем фразу. на случай наличия инфопорции. Иначе вылетит.
        --phr = dlg:AddPhrase("...",self:get_id(),self.task_info[v].completed_phrase_id,-10000)
        --phrase_script = phr:GetPhraseScript()
        --phrase_script:AddHasInfo(self.task_info[v].reward_info_portion)

        --local prid=self.task_info[v].completed_phrase_id
        --local first = true
        -- Добавляем диалог
        --for i,p in ipairs(self.task_info[v].reward_info_dialog) do
          --local cid=self:get_id()
          --phr = dlg:AddPhrase(p,cid,prid,-10000)
          --prid = cid
          --if first then
          --first = false
        --phrase_script = phr:GetPhraseScript()
        --phrase_script:AddGiveInfo(self.task_info[v].reward_info_portion)
        --phrase_script:AddAction("dialog_manager.info_received")
        --phrase_script:AddDontHasInfo(self.task_info[v].reward_info_portion)
          --end
        --end
      --end
    --end
  --end
       end
end

--' Регистрация целей для квестов.
function CRandomTask:register_target(obj)
    if IsStalker(obj) then
        --' Возможно регистрируется цель для квеста "убить сталкера"
        for k,v in pairs(self.task_id_by_type["kill_stalker"]) do
            if obj.alive ~= nil and obj:alive() == true and
                obj:profile_name() == self.task_info[v].target 
            then
                if self.task_info[v].target_objects == nil then
                    self.task_info[v].target_objects = {}
                end

                table.insert(self.task_info[v].target_objects, obj.id)
            end
        end

    elseif obj:clsid() == clsid.smart_terrain then
        --' Возможно регистрируется цель для квеста "вынести лагерь"
        for k,v in pairs(self.task_id_by_type["eliminate_lager"]) do
            if obj:name() == self.task_info[v].target then
                if self.task_info[v].target_objects == nil then
                    self.task_info[v].target_objects = {}
                end
                table.insert(self.task_info[v].target_objects, obj.id)
            end
        end
        --' Возможно регистрируется цель для квеста "вынести логово"
        for k,v in pairs(self.task_id_by_type["eliminate_lair"]) do
            if obj:name() == self.task_info[v].target then
                if self.task_info[v].target_objects == nil then
                    self.task_info[v].target_objects = {}
                end
                table.insert(self.task_info[v].target_objects, obj.id)
            end
        end
        --' Либо регистрируется цель для квеста "защитить лагерь"
        for k,v in pairs(self.task_id_by_type["defend_lager"]) do
            if obj:name() == self.task_info[v].target then
                --' Проверка что в кастом дате указано от кого защищать
                local sm_ini = obj:spawn_ini()
                local defend_target = utils.cfg_get_number(sm_ini, "random_task", "defend_target", nil, true)
                if self.task_info[v].target_objects == nil then
                    self.task_info[v].target_objects = {}
                end
                table.insert(self.task_info[v].target_objects, obj.id)
            end
        end

    else
        --' Возможно регистрируется цель для квеста "найти предмет"
        for k,v in pairs(self.task_id_by_type["find_item"]) do
            if obj:section_name() == self.task_info[v].target then
                if self.task_info[v].target_objects == nil then
                    self.task_info[v].target_objects = {}
                end
                table.insert(self.task_info[v].target_objects, obj.id)
            end
        end
    end
end
--' ОТРегистрация целей для квестов.
function CRandomTask:unregister_target(obj)
    if IsStalker(obj) then
        --' Возможно регистрируется цель для квеста "убить сталкера"
        for k,v in pairs(self.task_id_by_type["kill_stalker"]) do
            if self.task_info[v].target_objects ~= nil then
                for kk,vv in pairs(self.task_info[v].target_objects) do
                    if vv == obj.id then
                        table.remove(self.task_info[v].target_objects, vv)
                    end
                end
            end
        end
    elseif obj:clsid() == clsid.smart_terrain then
    else
        --' Возможно регистрируется цель для квеста "найти предмет"
        for k,v in pairs(self.task_id_by_type["find_item"]) do
            if self.task_info[v].target_objects ~= nil then
                for kk,vv in pairs(self.task_info[v].target_objects) do
                    if vv == obj.id then
                        table.remove(self.task_info[v].target_objects, vv)
                    end
                end
            end
        end
    end
end

function CRandomTask:stats(obj)
    for k,v in pairs(self.task_info) do
        if v.init_condition ~= nil then
--            printf("[%s] %s : %s", v.status, k, tostring(v.enabled_props))
--            print_table(v.init_condition)
        end
    end
end

function get_random_task()
    if random_task == nil then
        random_task = CRandomTask()
    end
    return random_task
end

function init_trader_task_dialog(dlg)
    get_random_task():init_task_dialog(dlg, "trader")
end
function init_barman_task_dialog(dlg)
    get_random_task():init_task_dialog(dlg, "barman")
end
function init_ecolog_task_dialog(dlg)
    get_random_task():init_task_dialog(dlg, "ecolog")
end
function init_dolg_task_dialog(dlg)
    get_random_task():init_task_dialog(dlg, "dolg")
end
function init_freedom_task_dialog(dlg)
    get_random_task():init_task_dialog(dlg, "freedom")
end

function init_shustriy_task_dialog(dlg)
    get_random_task():init_task_dialog(dlg, "shustriy")
end
function init_lisiy_task_dialog(dlg)
    get_random_task():init_task_dialog(dlg, "lisiy")
end
function init_hunter_task_dialog(dlg)
    get_random_task():init_task_dialog(dlg, "hunter")
end
function init_drunk_dolg_task_dialog(dlg)
    get_random_task():init_task_dialog(dlg, "drunk_dolg")
end
function init_petrenko_task_dialog(dlg)
    get_random_task():init_task_dialog(dlg, "petrenko")
end
function init_wolf_task_dialog(dlg)
    get_random_task():init_task_dialog(dlg, "wolf")
end
function init_zastava_commander_task_dialog(dlg)
    get_random_task():init_task_dialog(dlg, "zastava_commander")
end
function init_mercenary_task_dialog(dlg)
    get_random_task():init_task_dialog(dlg, "mercenary")
end
function init_pri_trader_task_dialog(dlg)
    get_random_task():init_task_dialog(dlg, "pri_trader")
end

function init_trader_reward_dialog(dlg)
    get_random_task():init_reward_dialog(dlg, "trader")
end
function init_barman_reward_dialog(dlg)
    get_random_task():init_reward_dialog(dlg, "barman")
end
function init_ecolog_reward_dialog(dlg)
    get_random_task():init_reward_dialog(dlg, "ecolog")
end
function init_dolg_reward_dialog(dlg)
    get_random_task():init_reward_dialog(dlg, "dolg")
end
function init_freedom_reward_dialog(dlg)
    get_random_task():init_reward_dialog(dlg, "freedom")
end

function init_shustriy_reward_dialog(dlg)
    get_random_task():init_reward_dialog(dlg, "shustriy")
end
function init_lisiy_reward_dialog(dlg)
    get_random_task():init_reward_dialog(dlg, "lisiy")
end
function init_hunter_reward_dialog(dlg)
    get_random_task():init_reward_dialog(dlg, "hunter")
end
function init_drunk_dolg_reward_dialog(dlg)
    get_random_task():init_reward_dialog(dlg, "drunk_dolg")
end
function init_petrenko_reward_dialog(dlg)
    get_random_task():init_reward_dialog(dlg, "petrenko")
end
function init_wolf_reward_dialog(dlg)
    get_random_task():init_reward_dialog(dlg, "wolf")
end
function init_zastava_commander_reward_dialog(dlg)
    get_random_task():init_reward_dialog(dlg, "zastava_commander")
end
function init_mercenary_reward_dialog(dlg)
    get_random_task():init_reward_dialog(dlg, "mercenary")
end
function init_pri_trader_reward_dialog(dlg)
    get_random_task():init_reward_dialog(dlg, "pri_trader")
end

function has_active_vendor_task(actor, npc)
    return get_random_task():active_parent_task(actor, npc)
end
function precondition_task_avail(actor, npc, p1, p2, p3)
    return get_random_task():task_avail(actor, npc, p1, p2, p3, false)
end
function precondition_active_task(actor, npc, p1, p2, p3)
    return get_random_task():active_task(actor, npc, p1, p2, p3)
end

function precondition_vendor_can_task(npc, actor, p1, p2, p3)
    return get_random_task():parent_can_task(actor, npc, p1, p2, p3)
end
function precondition_vendor_cannot_task(npc, actor, p1, p2, p3)
    return not get_random_task():parent_can_task(actor, npc, p1, p2, p3)
end
function precondition_have_completed_job(npc, actor, p1, p2, p3)
    return get_random_task():have_completed_job(actor, npc)
end
function precondition_dont_have_completed_job(npc, actor, p1, p2, p3)
    return not get_random_task():have_completed_job(actor, npc)
end

function action_task_show(npc, actor)
    get_random_task():action_task_show(npc, actor)
end

function action_give_task(actor, npc, p1, p2)
    get_random_task():action_give_task(actor, npc, p1, p2)
end

function action_refuse_task(npc, actor, p1, p2)
    get_random_task():action_refuse_task(npc, actor, p1, p2)
end

function action_task_reward(actor, npc, p1, p2)
    get_random_task():task_reward(actor, npc, p1, p2)
end

function reward_by_task(task)
    get_random_task():task_reward_storyline(task)
end

function task_complete(p1, p2)
    return get_random_task():task_complete(p1, p2)
end

function task_fail(p1, p2)
    return get_random_task():task_fail(p1, p2)
end

function task_callback(p1, p2, state)
    return get_random_task():task_callback(p1, p2, state)
end

function actor_update()
    get_random_task():actor_update()
end
function cleanup_actor()
    get_random_task():cleanup_actor()
end
function save(p)
    get_random_task():save(p)
end
function load(p)
    get_random_task():load(p)
end
function clear_task_manager()
    random_task     = nil
end

function wolf_is_on_cordon(actor, npc)
        local level_name = level.name()
        if level_name == "l01_escape" then
                return true
                else
                return false
         end
end

function wolf_is_on_military(actor, npc)
        local level_name = level.name()
        if level_name == "l07_military" then
                return true
                else
                return false
         end
end

function actor_is_on_military()
        local level_name = level.name()
        if level_name == "l07_military" then
                return true
                else
                return false
         end
end

function show_reward(actor,npc,p1,p2)
    local reward_text, reward_money, task_details

    if random_task == nil then
        random_task = task_manager.CRandomTask()
    end

        --строка ниже не работает
    task_details = random_task.task_info[random_task.task_id_by_init_phrase_id[p2-1]]

    if task_details == nil then return end

    reward_text = format_reward_text(task_details.reward_item)
    reward_money = task_details.reward_money

    local task_texture, task_rect = get_texture_info("ui_iconsTotal_find_item")
    if reward_text ~= nil and reward_text ~= "" then
        db.actor:give_talk_message("Получишь за это вот что:", "ui\\ui_iconstotal", Frect():set(0,0,10,10), "simple_answer_item")
        db.actor:give_talk_message(reward_text, task_texture, task_rect,"iconed_trade_info")
    end

    if reward_money ~= nil then
        task_texture, task_rect = get_texture_info("ui_iconsTotal_found_money")
        if task_details.need_return and reward_text == "" then
            db.actor:give_talk_message(reward_money .. " RU (" .. game.translate_string("return_for_reward") .. ")", task_texture, task_rect, "iconed_trade_info")
        else
            db.actor:give_talk_message(reward_money .. " RU", task_texture, task_rect,"iconed_trade_info")
        end
    end
end

function format_reward_text(reward_list)
    local i,v, ii, vv
    local rwd = {}
    local reward_text = ""
    if reward_list == nil then return "" end
    for i,v in pairs(reward_list) do
        if rwd[v] == nil then
            rwd[v] = 1
        else
            rwd[v] = rwd[v] + 1
        end
    end
    for i,v in pairs(rwd) do
        if v == 1 then
            reward_text = reward_text .. game.translate_string(news_manager.get_inv_name(i)) .. ", "
        else
            reward_text = reward_text .. string.format("%s",v) .. "x " .. game.translate_string(news_manager.get_inv_name(i)) .. ", "
        end
    end
    if string.len(reward_text) >=2 then
        reward_text = string.sub (reward_text, 1, string.len(reward_text)-2)
    end
    return reward_text
end
 

 

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

@Капрал Хикс  Привет, есть отдельный мини мод, посмотри как там реализовано

так я думаю проще будет

 

Show Reward Mini Mod v1.03

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

@ted.80 , заработало! Благо в ридми к этому минимоду есть разъяснение.

Оказывается, в одной строке у меня использовался метод, который в патче 1.0005 и выше имеет другой формат. А так как я брал готовое решение из мода АМК 1.4.1, который под патч 1.0004, то оно и не работало.

Подозреваю, что награда инфой за квест даёт вылет по схожей причине...

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

ChatGPT после некоторого обучения выдал мне рабочий скрипт отображения иконками на карте оружия... Теперь пытаюсь добавить в исключения оружие в инвентаре NPC и ГГ.

  • Нравится 1
Ссылка на комментарий
5 часов назад, Капрал Хикс сказал:

рабочий скрипт отображения иконками на карте оружия

 

Ну так поделись творением искусственного интеллекта - мы чай не тупее будем 

доработаем до удобоваримости

 

Поделюсь своим творением

 

local Dot = {
{"ammo","cheat_ammo_spot"},
{"medkit","cheat_medkit_spot"},
{"af_","cheat_af_spot"},
{"wpn_","cheat_wpn_spot"},
{"outfit","cheat_outfit_spot"}
}

function DelDot(obj)
	for k, v in pairs(Dot) do
		if level.map_has_object_spot(obj.id, v[2]) ~= 0 then
			for i = 1, level.map_has_object_spot(obj.id, v[2]) do
				level.map_remove_object_spot(obj.id, v[2])
			end
		end
	end
end

function Dots(obj)
	for k, v in pairs(Dot) do
		if string.find(obj:section_name(), v[1]) then
			if level.map_has_object_spot(obj.id, v[2]) == 0 then
				level.map_add_object_spot_ser(obj.id, v[2], game.translate_string(system_ini():r_string(obj:section_name(), "inv_name")))
			end
		end
	end
end

function ItemDot()
	for i = 1, 65534 do
		local obj = alife():object((i))
		if obj and obj.parent_id then
			if obj.parent_id == 65535 then
				Dots(obj)
			else
				DelDot(obj)
			end
		end
	end
end

 

Изменено пользователем ted.80
  • Полезно 2
Ссылка на комментарий
-- Функция для отображения оружия на земле на миникарте
function display_ground_weapons_on_minimap()
-- Радиус, в котором будет происходить поиск оружия на земле
local SEARCH_RADIUS = 20

-- Иконка-заглушка для оружия, если его иконка не определена
local default_weapon_icon = "info_npc_mapspot"

-- Таблица с иконками и названиями для разных типов оружия
local weapon_info = {
    ["wpn_ak74"] = {icon = "info_npc_mapspot", name = "wpn-ak74"},      -- АК-74
    ["wpn_lr300"] = {icon = "info_npc_mapspot", name = "wpn-lr300"},    -- LR300
    ["wpn_abakan"] = {icon = "info_npc_mapspot", name = "wpn-abakan"},  -- Абакан
    ["wpn_svd"] = {icon = "info_npc_mapspot", name = "wpn-svd"},        -- СВД
    ["wpn_rpg7"] = {icon = "info_npc_mapspot", name = "wpn-rpg7"},      -- РПГ-7
    -- Добавить другие виды оружия и иконки при необходимости
}

    -- Иконки выше  ставить свои, я их сейчас дорисовываю.
    -- Получаем главного персонажа (игрока) через db.actor
    local actor = db.actor

    -- Перебираем все объекты на текущей карте (в видимой зоне)
    for id = 1, 65535 do
        local obj = level.object_by_id(id)
        if obj then
            -- Проверяем, что объект является оружием и находится в радиусе 20 метров от игрока
            if obj:section():find("wpn_") and actor:position():distance_to(obj:position()) <= SEARCH_RADIUS then
                -- Получаем данные для этого оружия из таблицы
                local weapon_data = weapon_info[obj:section()]
                local weapon_icon = weapon_data and weapon_data.icon or default_weapon_icon
                local weapon_name = weapon_data and weapon_data.name or "unknown_weapon"

                -- Отображаем иконку и название оружия на миникарте
                level.map_add_object_spot(id, weapon_icon, weapon_name)
            end
        end
    end
end

function update()
    -- на апдейт в многострадальный bind_stalker.script: function actor_binder:update(delta): weap_show.update()
    -- Каждый игровой кадр обновляем отображение оружия на миникарте
    display_ground_weapons_on_minimap()
end

 

  • Полезно 2
  • Жуть! 1
Ссылка на комментарий

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

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

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

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

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

Войти

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

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

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