--'************************************************************************************* --' Дескриптор обычного задания --'************************************************************************************* local guiders_by_level = { ["zaton"]={["jupiter"]="zat_b215_stalker_guide_zaton", ["pripyat"]="zat_b215_stalker_guide_zaton"}, ["jupiter"]={["zaton"]="zat_b215_stalker_guide_jupiter", ["pripyat"]="jup_b43_stalker_assistant"}, ["pripyat"]={["zaton"]="jup_b43_stalker_assistant_pri", ["jupiter"]="jup_b43_stalker_assistant_pri"}, } function get_guider(target_level) local ln = level.name() if(guiders_by_level[ln] and guiders_by_level[ln][target_level]) then return get_story_object_id(guiders_by_level[ln][target_level]) end return nil end local valid_values = { complete = true, fail = true, reversed = true } --[[ C++ class task { const additional = 1; const completed = 2; const fail = 0; const in_progress = 1; const insignificant = 2; const storyline = 0; const task_dummy = 65535; }; ]] local status_by_id = { [0] = "normal", [1] = "selected", [2] = "completed", [3] = "fail", [4] = "reversed" } local id_by_status = { normal = 0, selected = 1, completed = 2, fail = 3, reversed = 4 } class "CGeneralTask" function CGeneralTask:__init(task_ini, id) self.task_ini = task_ini self.id = id self.title = utils.cfg_get_string(task_ini, id, "title", nil, false, "", "TITLE_DOESNT_EXIST") self.title_functor = utils.cfg_get_string(task_ini, id, "title_functor", nil, false, "", "condlist") self.current_title = nil self.descr = utils.cfg_get_string(task_ini, id, "descr", nil, false, "", "DESCR_DOESNT_EXIST") self.descr_functor = utils.cfg_get_string(task_ini, id, "descr_functor", nil, false, "", "condlist") self.current_descr = nil self.target = utils.cfg_get_string(task_ini, id, "target", nil, false, "", "DESCR_DOESNT_EXIST") self.target_functor = utils.cfg_get_string(task_ini, id, "target_functor", nil, false, "", "target_condlist") self.current_target = nil self.icon = utils.cfg_get_string(task_ini, id, "icon", nil, false, "", "ui_pda2_mtask_overlay") self.prior = utils.cfg_get_number(task_ini, id, "prior", nil, false, 0) self.storyline = utils.cfg_get_bool(task_ini, id, "storyline", nil, false, true) --' Условия выполнения и провала квеста local i = 0 self.condlist = {} while task_ini:line_exist(id, "condlist_"..i) do self.condlist[i] = xr_logic.parse_condlist(nil, "task_manager", "condlist", task_ini:r_string(id, "condlist_"..i)) i = i + 1 end --' Кондлисты на статусы квеста self.on_init = xr_logic.parse_condlist(nil, "task_manager", "condlist", utils.cfg_get_string(task_ini, id, "on_init", nil, false, "", "")) self.on_complete = xr_logic.parse_condlist(nil, "task_manager", "condlist", utils.cfg_get_string(task_ini, id, "on_complete", nil, false, "", "")) self.on_reversed = xr_logic.parse_condlist(nil, "task_manager", "condlist", utils.cfg_get_string(task_ini, id, "on_reversed", nil, false, "", "")) --' Награды за квест self.reward_money = xr_logic.parse_condlist(nil, "task_manager", "condlist", utils.cfg_get_string(task_ini, id, "reward_money", nil, false, "", "")) self.reward_item = xr_logic.parse_condlist(nil, "task_manager", "condlist", utils.cfg_get_string(task_ini, id, "reward_item", nil, false, "", "")) self.community_relation_delta_fail = utils.cfg_get_number(task_ini, id, "community_relation_delta_fail", nil, false, 0) self.community_relation_delta_complete = utils.cfg_get_number(task_ini, id, "community_relation_delta_complete", nil, false, 0) --' Статус квеста, может быть: "normal", "selected", "completed", "fail", "reversed" self.status = "normal" self.cached_condlist = {} -- MTB-marek.siemieniuk: cached condlist self.current_title = task_functor[self.title_functor](self.id, "title", self.title, self.cached_condlist) -- MTB-marek.siemieniuk: cached condlist self.current_descr = task_functor[self.descr_functor](self.id, "descr", self.descr, self.cached_condlist) -- MTB-marek.siemieniuk: cached condlist local time = 0 if self.wait_time ~= nil then time = self.wait_time -- Тут время задано в игровых секундах end if(self.storyline) then if time == 0 then self.spot = "storyline_task_location" else self.spot = "storyline_task_location_complex_timer" end else if time == 0 then self.spot = "secondary_task_location" else self.spot = "secondary_task_location_complex_timer" end end self.current_target = task_functor[self.target_functor](self.id, "target", self.target, self.cached_condlist) -- MTB-marek.siemieniuk: cached condlist self.dont_send_update_news = utils.cfg_get_bool(task_ini, id, "dont_send_update_news", nil, false, false) end --' Выдача квеста function CGeneralTask:give_task(community) local t = CGameTask() t:set_id(tostring(self.id)) if(self.storyline) then t:set_type(task.storyline) else t:set_type(task.additional) end t:set_title(self.current_title) t:set_description(self.current_descr) t:set_priority(self.prior) t:set_icon_name(self.icon) t:add_complete_func("task_manager.task_complete") t:add_fail_func("task_manager.task_fail") xr_logic.pick_section_from_condlist(db.actor, db.actor, self.on_init) if self.current_target ~= nil then t:set_map_location(self.spot) t:set_map_object_id(self.current_target) if(self.storyline) then level.map_add_object_spot(self.current_target, "ui_storyline_task_blink", "") else level.map_add_object_spot(self.current_target, "ui_secondary_task_blink", "") end end local time = 0 if self.wait_time ~= nil then time = self.wait_time -- Тут время задано в игровых секундах end --' Заносим в task_info self.status = "selected" self.inited_time = game.get_game_time() db.actor:give_task(t, time*10, false, time) self.t = t end --' Проверка текущего выполнения квеста function CGeneralTask:check_task(tm) local global_time = time_global() local task_updated = false if self.check_time ~= nil and self.last_check_task ~= nil and global_time - self.check_time <= 50 then --' Возвращаем результат прошлой проверки (для оптимизации) return end if self.t == nil then self.t = db.actor and db.actor:get_task(self.id, true) return end self.check_time = global_time local t_tile = task_functor[self.title_functor](self.id, "title", self.title, self.cached_condlist) -- MTB-marek.siemieniuk: cached condlist if self.current_title ~= t_tile then printf("task [%s] updated due to title change from [%s] to [%s]", tostring(self.id), tostring(self.current_title), tostring(t_tile)) task_updated = true self.current_title = t_tile self.t:set_title(game.translate_string(t_tile)) end local t_descr = task_functor[self.descr_functor](self.id, "descr", self.descr, self.cached_condlist) -- MTB-marek.siemieniuk: cached condlist if self.current_descr ~= t_descr then printf("task [%s] updated due to description change from [%s] to [%s]", tostring(self.id), tostring(self.current_descr), tostring(t_descr)) task_updated = true self.current_descr = t_descr self.t:set_description(game.translate_string(t_descr)) end local t_target = task_functor[self.target_functor](self.id, "target", self.target, self.cached_condlist) -- MTB-marek.siemieniuk: cached condlist self:check_level(t_target) if self.current_target ~= t_target then printf("task [%s] updated due to target change from [%s] to [%s]", tostring(self.id), tostring(self.current_target), tostring(t_target)) if self.current_target == nil then task_updated = true self.t:change_map_location(self.spot, t_target) if(self.storyline) then level.map_add_object_spot(t_target, "ui_storyline_task_blink", "") else level.map_add_object_spot(t_target, "ui_secondary_task_blink", "") end else if t_target == nil then self.t:remove_map_locations(false) task_updated = true else if(self.storyline) then level.map_add_object_spot(t_target, "ui_storyline_task_blink", "") else level.map_add_object_spot(t_target, "ui_secondary_task_blink", "") end self.t:change_map_location(self.spot, t_target) task_updated = true end end self.current_target = t_target end if task_updated and not(self.dont_send_update_news) then news_manager.send_task(db.actor, "updated", self.t) end for k,v in pairs(self.condlist) do local t = xr_logic.pick_section_from_condlist(db.actor, db.actor, v) if t ~= nil then --' Проверка на валидность if valid_values[t] ~= true then abort("Invalid task status [%s] for task [%s]", t, self.name) end self.last_check_task = t return end end end --' Инициализация награды function CGeneralTask:give_reward() xr_logic.pick_section_from_condlist(db.actor, db.actor, self.on_complete) local money = xr_logic.pick_section_from_condlist(db.actor, db.actor, self.reward_money) local items = xr_logic.pick_section_from_condlist(db.actor, db.actor, self.reward_item) -- Награду можно выдать двумя методами: от нпс или просто свалитьс неба. Если не найден НПС, с которым мы в диалоге, то просто валим с неба local npc = inventory_upgrades.victim if money ~= nil then dialogs.relocate_money(npc, tonumber(money), "in") end if items ~= nil then local ancillary_item_table = {} for k,v in pairs(utils.parse_names(items)) do if ancillary_item_table[v] == nil then ancillary_item_table[v] = 1 else ancillary_item_table[v] = ancillary_item_table[v] + 1 end end for k,v in pairs(ancillary_item_table) do dialogs.relocate_item_section(npc, k, "in", v) end end end function CGeneralTask:reverse_task() self.last_check_task = "reversed" end --' Деактивация квеста function CGeneralTask:deactivate_task(task) printf("deactivate task %s", self.id) self.check_time = nil if self.last_check_task == "fail" then news_manager.send_task(db.actor, "fail", task) elseif self.last_check_task == "reversed" then xr_logic.pick_section_from_condlist(db.actor, db.actor, self.on_reversed) news_manager.send_task(db.actor, "reversed", task) end self.last_check_task = nil self.status = "normal" end function CGeneralTask:check_level(target) if not(db.actor:is_active_task(self.t)) or not(target) then return end if not(level) then return end local s_obj = alife():object(target) if(s_obj) then local target_level = alife():level_name(game_graph():vertex(s_obj.m_game_vertex_id):level_id()) local level_name = level.name() if(level_name~=target_level) then local guider_id = get_guider(target_level) if not(guider_id) then return end local guider_spot = "" local guider_spot2 = "" if(self.storyline) then guider_spot = "storyline_task_on_guider" guider_spot2 = "secondary_task_on_guider" else guider_spot = "secondary_task_on_guider" guider_spot2 = "storyline_task_on_guider" end if(level.map_has_object_spot(guider_id, guider_spot2)~=0) then level.map_remove_object_spot(guider_id, guider_spot2) end if(guider_id and level.map_has_object_spot(guider_id, guider_spot)==0) then level.map_add_object_spot(guider_id, guider_spot, "") end else self:remove_guider_spot() end end end function CGeneralTask:remove_guider_spot(target) if not(guiders_by_level[level.name()]) then return end for k,v in pairs(guiders_by_level[level.name()]) do local guider_id = get_story_object_id(v) if(guider_id) then if(level.map_has_object_spot(guider_id, "storyline_task_on_guider")~=0) then level.map_remove_object_spot(guider_id, "storyline_task_on_guider") end if(level.map_has_object_spot(guider_id, "secondary_task_on_guider")~=0) then level.map_remove_object_spot(guider_id, "secondary_task_on_guider") end end end end -- Save quest function CGeneralTask:save(packet) set_save_marker(packet, "save", false, "CGeneralTask") packet:w_u8(id_by_status[self.status]) utils.w_CTime(packet, self.inited_time) packet:w_stringZ(self.current_title) packet:w_stringZ(self.current_descr) packet:w_stringZ(tostring(self.current_target)) set_save_marker(packet, "save", true, "CGeneralTask") end -- Load quest function CGeneralTask:load(packet) set_save_marker(packet, "load", false, "CGeneralTask") self.status = status_by_id[packet:r_u8()] self.inited_time = utils.r_CTime(packet) self.current_title = packet:r_stringZ() self.current_descr = packet:r_stringZ() self.current_target = packet:r_stringZ() if self.current_target == "nil" then self.current_target = nil else self.current_target = tonumber(self.current_target) end set_save_marker(packet, "load", true, "CGeneralTask") end