Norman Eisenherz 316 Опубликовано 4 Сентября Поделиться Опубликовано 4 Сентября Если я правильно понял, это значение task_info.id.complex_type, которое для цикличек выглядит как type_parent. Пример: id = barmen_kill_stalker_5 complex_type = kill_stalker_barman Мини-моды: ТЧ ЧН ЗП Шпаргалка Ссылка на комментарий
ARTLantist 14 Опубликовано 4 Сентября Поделиться Опубликовано 4 Сентября @Norman Eisenherz ну мне конкретно нужен этот id. Именно получить его, чтобы я мог прописать local id = что-то, и чтобы это "что-то" выдало мне мой id квеста (в частном случае "tm_monster_part_1"), чтобы я потом прописал local task_desc = self.task_info[id] И уже от этого плясал и везде были свои данные конкретно этого квеста 1 Ссылка на комментарий
Norman Eisenherz 316 Опубликовано 4 Сентября Поделиться Опубликовано 4 Сентября 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 Сентября Поделиться Опубликовано 5 Сентября (изменено) 04.09.2024 в 21:19, 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 Сентября пользователем ARTLantist Ссылка на комментарий
Norman Eisenherz 316 Опубликовано 5 Сентября Поделиться Опубликовано 5 Сентября Проверил таблицу: данные точно заполняются, причем ключи phrase_id, как и в обработчике action, являются текстом – не было ли при сверке перевода в число? Мини-моды: ТЧ ЧН ЗП Шпаргалка Ссылка на комментарий
Капрал Хикс 535 Опубликовано 6 Сентября Поделиться Опубликовано 6 Сентября Хочу отследить момент взятия квеста на поиск артефакта и передать ГГ предмет, нужный для этого квеста в диалоге. Где бы поставить проверку на взятие квеста для этого? Ссылка на комментарий
Norman Eisenherz 316 Опубликовано 6 Сентября Поделиться Опубликовано 6 Сентября (изменено) AddAction + yes_phrase_id + task_id аналогично тому, что описано выше, если это циклический квест. Edit: даже проще – если заголовок конфига известен заранее, достаточно добавить в тот же CRandomTask:init_task_dialog проверку if v.name == "tm_find_artefact_1" then … yes_phrase:AddAction(…) Изменено 6 Сентября пользователем Norman Eisenherz 1 1 Мини-моды: ТЧ ЧН ЗП Шпаргалка Ссылка на комментарий
Капрал Хикс 535 Опубликовано 7 Сентября Поделиться Опубликовано 7 Сентября (изменено) 06.09.2024 в 21: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 Сентября пользователем Капрал Хикс Ссылка на комментарий
Norman Eisenherz 316 Опубликовано 7 Сентября Поделиться Опубликовано 7 Сентября 1. Надо привязаться к yes_phrase; действие "give_task" уже ссылается на нее – свое действие с проверкой ставить рядом. 2. Сообщение выдается при передаче предметов через обертку dialogs.relocate_item_section(…), которая ссылается на news_manager.script. 1 Мини-моды: ТЧ ЧН ЗП Шпаргалка Ссылка на комментарий
Капрал Хикс 535 Опубликовано 8 Сентября Поделиться Опубликовано 8 Сентября (изменено) @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 Сентября пользователем Капрал Хикс Ссылка на комментарий
ted.80 278 Опубликовано 8 Сентября Поделиться Опубликовано 8 Сентября @Капрал Хикс Привет, есть отдельный мини мод, посмотри как там реализовано так я думаю проще будет Show Reward Mini Mod v1.03 2 1 Личный АРХИВ по S.T.A.L.K.E.R Ссылка на комментарий
Капрал Хикс 535 Опубликовано 8 Сентября Поделиться Опубликовано 8 Сентября @ted.80 , заработало! Благо в ридми к этому минимоду есть разъяснение. Оказывается, в одной строке у меня использовался метод, который в патче 1.0005 и выше имеет другой формат. А так как я брал готовое решение из мода АМК 1.4.1, который под патч 1.0004, то оно и не работало. Подозреваю, что награда инфой за квест даёт вылет по схожей причине... 1 Ссылка на комментарий
Капрал Хикс 535 Опубликовано 15 Сентября Поделиться Опубликовано 15 Сентября ChatGPT после некоторого обучения выдал мне рабочий скрипт отображения иконками на карте оружия... Теперь пытаюсь добавить в исключения оружие в инвентаре NPC и ГГ. 1 Ссылка на комментарий
ted.80 278 Опубликовано 15 Сентября Поделиться Опубликовано 15 Сентября (изменено) 15.09.2024 в 12:00, Капрал Хикс сказал: рабочий скрипт отображения иконками на карте оружия Ну так поделись творением искусственного интеллекта - мы чай не тупее будем доработаем до удобоваримости Поделюсь своим творением 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 endlocal 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 Сентября пользователем ted.80 2 Личный АРХИВ по S.T.A.L.K.E.R Ссылка на комментарий
Капрал Хикс 535 Опубликовано 15 Сентября Поделиться Опубликовано 15 Сентября -- Функция для отображения оружия на земле на миникарте 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-- Функция для отображения оружия на земле на миникарте 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 316 Опубликовано 16 Сентября Поделиться Опубликовано 16 Сентября Избыток ручного ввода. Заголовки секций и перевод названий можно получить из конфигов каждого объекта, а название метки построить по шаблону вроде "section_mapspot" и выбросить всю таблицу weapon_info – вручную останется только создать однотипные описания меток "wpn_name_mapspot" в XML-файле. Вместо перебора можно привязать создание/удаление меток к сбросу/поднятию оружия на стороне ГГ и сбросу из инвентаря NPC в [death_manager.script]. 1 1 Мини-моды: ТЧ ЧН ЗП Шпаргалка Ссылка на комментарий
mole venomous 3 433 Опубликовано 16 Сентября Поделиться Опубликовано 16 Сентября Ну перебор всех объектов на постоянном апдейте это что то вообще очень жесткое... 1 1 Здесь могла быть ваша реклама. Ссылка на комментарий
Капрал Хикс 535 Опубликовано 16 Сентября Поделиться Опубликовано 16 Сентября @mole venomous , согласен. Но пока на пробу сделал как на ум пришло:). @Norman Eisenherz , в целом ход мыслей понял, упростим... По последнему пункту: как быть с оружием, которое не выбрасывалось НПС или ГГ, а мирно себе лежит в олл.спавне/скриптом заспавнено в начале игры? Ссылка на комментарий
ted.80 278 Опубликовано 16 Сентября Поделиться Опубликовано 16 Сентября (изменено) 16.09.2024 в 13:43, Капрал Хикс сказал: а мирно себе лежит в олл.спавне/скриптом заспавнено в начале игры? Ну так для него и сделай перебор - только по какому либо условию, а не на апдейте @Norman Eisenherz Вместо перебора можно привязать создание/удаление меток к сбросу/поднятию оружия на стороне ГГ и сбросу из инвентаря NPC в [death_manager.script]. Изменено 16 Сентября пользователем ted.80 Личный АРХИВ по S.T.A.L.K.E.R Ссылка на комментарий
Капрал Хикс 535 Опубликовано 16 Сентября Поделиться Опубликовано 16 Сентября 16.09.2024 в 14:25, ted.80 сказал: только по какому либо условию, а не на апдейте Ну вот на ум ничего не приходит. Как ещё проверить кроме перебора оружие в радиусе... Ссылка на комментарий
Рекомендуемые сообщения
Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий
Комментарии могут оставлять только зарегистрированные пользователи
Создать аккаунт
Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!
Зарегистрировать новый аккаунтВойти
Есть аккаунт? Войти.
Войти