Norman Eisenherz 317 Опубликовано 4 Сентября 2024 Поделиться Опубликовано 4 Сентября 2024 Если я правильно понял, это значение task_info.id.complex_type, которое для цикличек выглядит как type_parent. Пример: id = barmen_kill_stalker_5 complex_type = kill_stalker_barman Мини-моды: ТЧ ЧН ЗП Шпаргалка Ссылка на комментарий
ARTLantist 14 Опубликовано 4 Сентября 2024 Поделиться Опубликовано 4 Сентября 2024 @Norman Eisenherz ну мне конкретно нужен этот id. Именно получить его, чтобы я мог прописать local id = что-то, и чтобы это "что-то" выдало мне мой id квеста (в частном случае "tm_monster_part_1"), чтобы я потом прописал local task_desc = self.task_info[id] И уже от этого плясал и везде были свои данные конкретно этого квеста 1 Ссылка на комментарий
Norman Eisenherz 317 Опубликовано 4 Сентября 2024 Поделиться Опубликовано 4 Сентября 2024 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 Мини-моды: ТЧ ЧН ЗП Шпаргалка Ссылка на комментарий
ARTLantist 14 Опубликовано 5 Сентября 2024 Поделиться Опубликовано 5 Сентября 2024 (изменено) 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, но всё работает. Благодарю, что направил в нужное русло Изменено 5 Сентября 2024 пользователем ARTLantist Ссылка на комментарий
Norman Eisenherz 317 Опубликовано 5 Сентября 2024 Поделиться Опубликовано 5 Сентября 2024 Проверил таблицу: данные точно заполняются, причем ключи phrase_id, как и в обработчике action, являются текстом – не было ли при сверке перевода в число? Мини-моды: ТЧ ЧН ЗП Шпаргалка Ссылка на комментарий
Капрал Хикс 540 Опубликовано 6 Сентября 2024 Поделиться Опубликовано 6 Сентября 2024 Хочу отследить момент взятия квеста на поиск артефакта и передать ГГ предмет, нужный для этого квеста в диалоге. Где бы поставить проверку на взятие квеста для этого? Ссылка на комментарий
Norman Eisenherz 317 Опубликовано 6 Сентября 2024 Поделиться Опубликовано 6 Сентября 2024 (изменено) AddAction + yes_phrase_id + task_id аналогично тому, что описано выше, если это циклический квест. Edit: даже проще – если заголовок конфига известен заранее, достаточно добавить в тот же CRandomTask:init_task_dialog проверку if v.name == "tm_find_artefact_1" then … yes_phrase:AddAction(…) Изменено 6 Сентября 2024 пользователем Norman Eisenherz 1 1 Мини-моды: ТЧ ЧН ЗП Шпаргалка Ссылка на комментарий
Капрал Хикс 540 Опубликовано 7 Сентября 2024 Поделиться Опубликовано 7 Сентября 2024 (изменено) 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 Уже разобрался. Пост под снос. Изменено 8 Сентября 2024 пользователем Капрал Хикс Ссылка на комментарий
Norman Eisenherz 317 Опубликовано 7 Сентября 2024 Поделиться Опубликовано 7 Сентября 2024 1. Надо привязаться к yes_phrase; действие "give_task" уже ссылается на нее – свое действие с проверкой ставить рядом. 2. Сообщение выдается при передаче предметов через обертку dialogs.relocate_item_section(…), которая ссылается на news_manager.script. 1 Мини-моды: ТЧ ЧН ЗП Шпаргалка Ссылка на комментарий
Капрал Хикс 540 Опубликовано 8 Сентября 2024 Поделиться Опубликовано 8 Сентября 2024 (изменено) @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 endend --' Отказ игроком от квеста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 endend --' Проверяем, не выполнен ли таск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 falseend --' Проверяем, не профейлен ли таск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 falseend--' Обнуление переменных при завершении или провале таска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 endend--' Выводит список доступных квестов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 endend--' 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 == nilend--' Проверка свойств таска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 endend--' Проверяем можем ли мы сейчас выдать какой либо самоинициализующийся таск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 endend--' Функция для аварийной зачистки - убирает у неактивных квестов дату последнего обращения, список объектов и текущий объект,--' в результате чего позволяет освободить довольно приличное количество места в хранилище ГГ, KamikaZzefunction 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 endend--' Проверяется является ли текущий таск выданным игроку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 endend--' Функция, в которой будет выдаваться вещевая награда за выполненные сторилайновые квесты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) endend--' Создается диалог актера, в котором будут приниматься задания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 endend --' Регистрация целей для квестов.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 endend--' ОТРегистрация целей для квестов.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 endend 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 endend function get_random_task() if random_task == nil then random_task = CRandomTask() end return random_taskend function init_trader_task_dialog(dlg) get_random_task():init_task_dialog(dlg, "trader")endfunction init_barman_task_dialog(dlg) get_random_task():init_task_dialog(dlg, "barman")endfunction init_ecolog_task_dialog(dlg) get_random_task():init_task_dialog(dlg, "ecolog")endfunction init_dolg_task_dialog(dlg) get_random_task():init_task_dialog(dlg, "dolg")endfunction 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")endfunction init_lisiy_task_dialog(dlg) get_random_task():init_task_dialog(dlg, "lisiy")endfunction init_hunter_task_dialog(dlg) get_random_task():init_task_dialog(dlg, "hunter")endfunction init_drunk_dolg_task_dialog(dlg) get_random_task():init_task_dialog(dlg, "drunk_dolg")endfunction init_petrenko_task_dialog(dlg) get_random_task():init_task_dialog(dlg, "petrenko")endfunction init_wolf_task_dialog(dlg) get_random_task():init_task_dialog(dlg, "wolf")endfunction init_zastava_commander_task_dialog(dlg) get_random_task():init_task_dialog(dlg, "zastava_commander")endfunction init_mercenary_task_dialog(dlg) get_random_task():init_task_dialog(dlg, "mercenary")endfunction 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")endfunction init_barman_reward_dialog(dlg) get_random_task():init_reward_dialog(dlg, "barman")endfunction init_ecolog_reward_dialog(dlg) get_random_task():init_reward_dialog(dlg, "ecolog")endfunction init_dolg_reward_dialog(dlg) get_random_task():init_reward_dialog(dlg, "dolg")endfunction 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")endfunction init_lisiy_reward_dialog(dlg) get_random_task():init_reward_dialog(dlg, "lisiy")endfunction init_hunter_reward_dialog(dlg) get_random_task():init_reward_dialog(dlg, "hunter")endfunction init_drunk_dolg_reward_dialog(dlg) get_random_task():init_reward_dialog(dlg, "drunk_dolg")endfunction init_petrenko_reward_dialog(dlg) get_random_task():init_reward_dialog(dlg, "petrenko")endfunction init_wolf_reward_dialog(dlg) get_random_task():init_reward_dialog(dlg, "wolf")endfunction init_zastava_commander_reward_dialog(dlg) get_random_task():init_reward_dialog(dlg, "zastava_commander")endfunction init_mercenary_reward_dialog(dlg) get_random_task():init_reward_dialog(dlg, "mercenary")endfunction 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)endfunction precondition_task_avail(actor, npc, p1, p2, p3) return get_random_task():task_avail(actor, npc, p1, p2, p3, false)endfunction 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)endfunction precondition_vendor_cannot_task(npc, actor, p1, p2, p3) return not get_random_task():parent_can_task(actor, npc, p1, p2, p3)endfunction precondition_have_completed_job(npc, actor, p1, p2, p3) return get_random_task():have_completed_job(actor, npc)endfunction 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()endfunction cleanup_actor() get_random_task():cleanup_actor()endfunction save(p) get_random_task():save(p)endfunction load(p) get_random_task():load(p)endfunction clear_task_manager() random_task = nilend function wolf_is_on_cordon(actor, npc) local level_name = level.name() if level_name == "l01_escape" then return true else return false endend function wolf_is_on_military(actor, npc) local level_name = level.name() if level_name == "l07_military" then return true else return false endend function actor_is_on_military() local level_name = level.name() if level_name == "l07_military" then return true else return false endend 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 endend 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_textend Изменено 8 Сентября 2024 пользователем Капрал Хикс Ссылка на комментарий
ted.80 313 Опубликовано 8 Сентября 2024 Поделиться Опубликовано 8 Сентября 2024 @Капрал Хикс Привет, есть отдельный мини мод, посмотри как там реализовано так я думаю проще будет Show Reward Mini Mod v1.03 2 1 Личный АРХИВ по S.T.A.L.K.E.R Ссылка на комментарий
Капрал Хикс 540 Опубликовано 8 Сентября 2024 Поделиться Опубликовано 8 Сентября 2024 @ted.80 , заработало! Благо в ридми к этому минимоду есть разъяснение. Оказывается, в одной строке у меня использовался метод, который в патче 1.0005 и выше имеет другой формат. А так как я брал готовое решение из мода АМК 1.4.1, который под патч 1.0004, то оно и не работало. Подозреваю, что награда инфой за квест даёт вылет по схожей причине... 1 Ссылка на комментарий
Капрал Хикс 540 Опубликовано 15 Сентября 2024 Поделиться Опубликовано 15 Сентября 2024 ChatGPT после некоторого обучения выдал мне рабочий скрипт отображения иконками на карте оружия... Теперь пытаюсь добавить в исключения оружие в инвентаре NPC и ГГ. 1 Ссылка на комментарий
ted.80 313 Опубликовано 15 Сентября 2024 Поделиться Опубликовано 15 Сентября 2024 (изменено) 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 Изменено 15 Сентября 2024 пользователем ted.80 2 Личный АРХИВ по S.T.A.L.K.E.R Ссылка на комментарий
Капрал Хикс 540 Опубликовано 15 Сентября 2024 Поделиться Опубликовано 15 Сентября 2024 -- Функция для отображения оружия на земле на миникарте 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 Ссылка на комментарий
Norman Eisenherz 317 Опубликовано 16 Сентября 2024 Поделиться Опубликовано 16 Сентября 2024 Избыток ручного ввода. Заголовки секций и перевод названий можно получить из конфигов каждого объекта, а название метки построить по шаблону вроде "section_mapspot" и выбросить всю таблицу weapon_info – вручную останется только создать однотипные описания меток "wpn_name_mapspot" в XML-файле. Вместо перебора можно привязать создание/удаление меток к сбросу/поднятию оружия на стороне ГГ и сбросу из инвентаря NPC в [death_manager.script]. 1 1 Мини-моды: ТЧ ЧН ЗП Шпаргалка Ссылка на комментарий
mole venomous 3 496 Опубликовано 16 Сентября 2024 Поделиться Опубликовано 16 Сентября 2024 Ну перебор всех объектов на постоянном апдейте это что то вообще очень жесткое... 1 1 Здесь могла быть ваша реклама. Ссылка на комментарий
Капрал Хикс 540 Опубликовано 16 Сентября 2024 Поделиться Опубликовано 16 Сентября 2024 @mole venomous , согласен. Но пока на пробу сделал как на ум пришло:). @Norman Eisenherz , в целом ход мыслей понял, упростим... По последнему пункту: как быть с оружием, которое не выбрасывалось НПС или ГГ, а мирно себе лежит в олл.спавне/скриптом заспавнено в начале игры? Ссылка на комментарий
ted.80 313 Опубликовано 16 Сентября 2024 Поделиться Опубликовано 16 Сентября 2024 (изменено) 43 минуты назад, Капрал Хикс сказал: а мирно себе лежит в олл.спавне/скриптом заспавнено в начале игры? Ну так для него и сделай перебор - только по какому либо условию, а не на апдейте @Norman Eisenherz Вместо перебора можно привязать создание/удаление меток к сбросу/поднятию оружия на стороне ГГ и сбросу из инвентаря NPC в [death_manager.script]. Изменено 16 Сентября 2024 пользователем ted.80 Личный АРХИВ по S.T.A.L.K.E.R Ссылка на комментарий
Капрал Хикс 540 Опубликовано 16 Сентября 2024 Поделиться Опубликовано 16 Сентября 2024 3 часа назад, ted.80 сказал: только по какому либо условию, а не на апдейте Ну вот на ум ничего не приходит. Как ещё проверить кроме перебора оружие в радиусе... Ссылка на комментарий
Рекомендуемые сообщения
Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий
Комментарии могут оставлять только зарегистрированные пользователи
Создать аккаунт
Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!
Зарегистрировать новый аккаунтВойти
Есть аккаунт? Войти.
Войти