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

Скриптование


Svoboда

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

@Labadal , добавил строчку с выводом в лог, получил в консоли красным такое при заходе в спейс-рестриктор:

! Unknown command:   -1

Вылета нет.

Поделиться этим сообщением


Ссылка на сообщение

@Labadal , очень странно... Буду перепроверять все названия, может где-то опечатка.

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

Поделиться этим сообщением


Ссылка на сообщение

Разобрался... Работает, но есть нюанс. Корректно проверяется название взятого квеста из файла game_tasks_by_vendor.xml, например eliminate_lager_trader. Т.е., как я понимаю, проверяется наличие взятого у квестодателя любого квеста данного типа. Если подставить название конкретного квеста из task_manager.ltx, например tm_eliminate_camp_1, то проверка не срабатывает.

Поделиться этим сообщением


Ссылка на сообщение
3 часа назад, naxac сказал:

нужно это делать в task_manager.script

Вот там я и завис. Ну, пока меня и такой вариант устроит.

Ещё бы награду информацией (инфопоршнем) за выполнение квеста прикрутить из АМК, но опять натыкаюсь на вылеты. Когда-то бы прикрутил на раз. Наверное сюда ткнусь за помощью.

Поделиться этим сообщением


Ссылка на сообщение

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

Поделиться этим сообщением


Ссылка на сообщение
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

 

 

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

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

Поделиться этим сообщением


Ссылка на сообщение

@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
 

 

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

Поделиться этим сообщением


Ссылка на сообщение

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

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

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

  • Нравится 1

Поделиться этим сообщением


Ссылка на сообщение

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

  • Нравится 1

Поделиться этим сообщением


Ссылка на сообщение
-- Функция для отображения оружия на земле на миникарте
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

Поделиться этим сообщением


Ссылка на сообщение

@mole venomous , согласен. Но пока на пробу сделал как на ум пришло:).

@Norman Eisenherz , в целом ход мыслей понял, упростим... По последнему пункту: как быть с оружием, которое не выбрасывалось НПС или ГГ, а мирно себе лежит в олл.спавне/скриптом заспавнено в начале игры?

Поделиться этим сообщением


Ссылка на сообщение
3 часа назад, ted.80 сказал:

только по какому либо условию, а не на апдейте

Ну вот на ум ничего не приходит. Как ещё проверить кроме перебора оружие в радиусе...

Поделиться этим сообщением


Ссылка на сообщение

Смотрю в скрипт sound_theme.script...

В чём разница между:

ph_snd_themes["gar_bandits_seryi"] =   {[[characters_voice\scenario\garbage\grey_bandit_1]],
                    [[characters_voice\scenario\garbage\grey_bandit_2]],
                    [[characters_voice\scenario\garbage\grey_bandit_3]],
                    [[characters_voice\scenario\garbage\grey_bandit_4]],
                    [[characters_voice\scenario\garbage\grey_bandit_5]]}

и

ph_snd_themes["gar_bandits_seryi"] =   {"characters_voice\\scenario\\garbage\\grey_bandit_1",
                                        "characters_voice\\scenario\\garbage\\grey_bandit_2",
                                        "characters_voice\\scenario\\garbage\\grey_bandit_3",
                                        "characters_voice\\scenario\\garbage\\grey_bandit_4",
                                        "characters_voice\\scenario\\garbage\\grey_bandit_5"}

?

В первом случае это так оно закомментировано как неиспользуемое что ли?

Поделиться этим сообщением


Ссылка на сообщение

Возможно ли скриптово отследить подсвечивание названия предмета по клавише F, когда он рядом лежит?

 

Поделиться этим сообщением


Ссылка на сообщение

Подскажите, как заставить один гулаг (с НПС) игнорировать другой? (С одной собакой в нём...).

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

Поделиться этим сообщением


Ссылка на сообщение

Можно ли отследить, что ГГ обыскивает труп именно мутанта и в таком случае не отображать отношение мутанта к ГГ (баг с "другом")?

Поделиться этим сообщением


Ссылка на сообщение
34 минуты назад, Stalkersof сказал:

чтоб повторно скрипт не срабатывал на уже поднятый предмет.

Делай проще. Выдавай инфопоршень при наличии у ГГ предмета. На поршень повесь выдачу бонуса.

  • Спасибо 1
  • Нравится 1
  • Согласен 1

Поделиться этим сообщением


Ссылка на сообщение

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

Поделиться этим сообщением


Ссылка на сообщение
  • Недавно просматривали   0 пользователей

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