e4s-sdk/gamedata/scripts/task_objects.script
2026-06-17 23:06:51 +03:00

364 lines
13 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

--'*************************************************************************************
--' Дескриптор обычного задания
--'*************************************************************************************
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