local travel_class = nil class "Ctraveler" function Ctraveler:__init() local ini_file = ini_file("misc\\travel_manager.ltx") local id, value, category = "", "", "" self.smart_to_stringtables = {} for i=0, ini_file:line_count("locations")-1 do temp1, id, value = ini_file:r_line("locations", i, "", "") self.smart_to_stringtables[id] = value end self.smart_travels = {} self.smart_by_phrase = {} for i=0, ini_file:line_count("traveler")-1 do temp1, id, value = ini_file:r_line("traveler", i, "", "") self.smart_travels[id] = {} self.smart_travels[id].name = ini_file:r_string(id, "name") self.smart_travels[id].level = ini_file:r_string(id, "level") self.smart_travels[id].condlist = xr_logic.parse_condlist(db.actor, id, "close_distance", ini_file:r_string(id, "condlist")) self.smart_travels[id].phrase_id = tostring(1000+i) self.smart_by_phrase[self.smart_travels[id].phrase_id] = id end end function get_travel_class() if travel_class == nil then travel_class = Ctraveler() end return travel_class end -- Initialize new actor dialog function init_traveler_dialog(dialog) local npc = db.actor local npc_community = "stalker" --npc:character_community() local actor_phrase = dialog:AddPhrase("dm_traveler_what_are_you_doing", "0", "", -10000) local actor_script = actor_phrase:GetPhraseScript() local npc_phrase = dialog:AddPhrase("if you see this - this is bad", "1", "0", -10000) local npc_phrase_script = npc_phrase:GetPhraseScript() npc_phrase_script:SetScriptText("travel_manager.squad_action_description") -- Может ли игрок пойти с ними actor_phrase = dialog:AddPhrase("dm_traveler_can_i_go_with_you", "11", "1", -10000) actor_script = actor_phrase:GetPhraseScript() actor_script:AddPrecondition("travel_manager.squad_on_move") npc_phrase = dialog:AddPhrase("dm_traveler_"..npc_community.."_actor_companion_yes", "111", "11", -10000) npc_phrase_script = npc_phrase:GetPhraseScript() npc_phrase_script:AddPrecondition("travel_manager.squad_can_take_actor") actor_phrase = dialog:AddPhrase("dm_traveler_actor_go_with_squad", "1111", "111", -10000) actor_script = actor_phrase:GetPhraseScript() actor_script:AddAction("travel_manager.actor_go_with_squad") actor_phrase = dialog:AddPhrase("dm_traveler_actor_dont_go_with_squad", "1112", "111", -10000) npc_phrase = dialog:AddPhrase("dm_traveler_"..npc_community.."_actor_companion_no", "112", "11", -10000) npc_phrase_script = npc_phrase:GetPhraseScript() npc_phrase_script:AddPrecondition("travel_manager.squad_cannot_take_actor") -- Игрок просит разрешения провести его actor_phrase = dialog:AddPhrase("dm_traveler_take_me_to", "12", "1", -10000) npc_phrase = dialog:AddPhrase("dm_traveler_"..npc_community.."_where_do_you_want", "121", "12", -10000) npc_phrase_script = npc_phrase:GetPhraseScript() npc_phrase_script:AddPrecondition("travel_manager.squad_can_travel") -- Формирование таргетов для проводников local travel_class = get_travel_class() for k,v in pairs(travel_class.smart_travels) do actor_phrase = dialog:AddPhrase(game.translate_string(v.name)..".", v.phrase_id, "121", -10000) actor_script = actor_phrase:GetPhraseScript() actor_script:AddPrecondition("travel_manager.travel_condlist") npc_phrase = dialog:AddPhrase("if you see this - this is bad", v.phrase_id.."_1", v.phrase_id, -10000) npc_phrase_script = npc_phrase:GetPhraseScript() npc_phrase_script:SetScriptText("travel_manager.get_travel_cost") actor_phrase = dialog:AddPhrase("dm_traveler_actor_agree", v.phrase_id.."_11", v.phrase_id.."_1", -10000) actor_script = actor_phrase:GetPhraseScript() actor_script:AddAction("travel_manager.actor_travel_with_squad") actor_script:AddPrecondition("travel_manager.actor_have_money") actor_phrase = dialog:AddPhrase("dm_traveler_actor_has_no_money", v.phrase_id.."_13", v.phrase_id.."_1", -10000) actor_script = actor_phrase:GetPhraseScript() actor_script:AddPrecondition("travel_manager.actor_have_not_money") actor_phrase = dialog:AddPhrase("dm_traveler_actor_refuse", v.phrase_id.."_14", v.phrase_id.."_1", -10000) end actor_phrase = dialog:AddPhrase("dm_traveler_actor_refuse", "1211", "121", -10000) npc_phrase = dialog:AddPhrase("dm_traveler_"..npc_community.."_i_cant_travel", "122", "12", -10000) npc_phrase_script = npc_phrase:GetPhraseScript() npc_phrase_script:AddPrecondition("travel_manager.squad_cannot_travel") -- Игрок выходит из диалога actor_phrase = dialog:AddPhrase("dm_traveler_bye", "13", "1", -10000) end function uni_traveler_precond(actor, npc) local squad = get_object_squad(npc) if squad ~= nil and squad:commander_id() ~= npc:id() then return false end if npc:character_community() == "bandit" then return false end if npc:character_community() == "army" then return false end local smart = xr_gulag.get_npc_smart(npc) if (smart) then if smart:name() == "jup_b41" then return false end end return true end -- Перенос игрока и отряда local init_time = nil local traveler_actor_path = nil local traveler_squad_path = nil local traveler_squad = nil local traveler_distance = nil local teleport_flag = nil local traveler_smart_id = nil function check_squad_for_enemies(squad_obj) for k in squad_obj:squad_members() do if relation_registry.get_general_goodwill_between(k.id, alife():actor().id) <= game_relations.ENEMIES then return true end end return false end function traveling() if time_global() - init_time < 3000 then return end if teleport_flag == false then printf("trvelling_squad_path [%s] travelling_actor_path [%s]!!!", tostring(traveler_squad_path), tostring(traveler_actor_path)) local point = patrol(traveler_actor_path) --local dir = vector():sub( point:point(0), point:point(1) ):getH() --local dir = vector():sub( point:point(1), point:point(0) ):normalize():getH() local dir = -point:point(1):sub(point:point(0)):getH() local board = sim_board.get_sim_board() for k,v in pairs(board.smarts[traveler_smart_id].squads) do if get_object_story_id(v.id) == nil and check_squad_for_enemies(v) then board:exit_smart(v, traveler_smart_id) board:remove_squad(v) end end local curr_smart_id = traveler_squad.smart_id if curr_smart_id ~= nil then board:assign_squad_to_smart(traveler_squad, nil) board:assign_squad_to_smart(traveler_squad, curr_smart_id) end local position = patrol(traveler_squad_path):point(0) traveler_squad:set_squad_position(position) teleport_flag = true db.actor:set_actor_direction(dir) db.actor:set_actor_position(point:point(0)) local minutes = traveler_distance/10 -- Сколько минут нужно, чтобы пройти расстояние со скоростью 6 км/ч (100 метров в минуту) + Так как у нас время идет в 10 раз быстрее local hours = math.floor(minutes/60) minutes = minutes - hours*60 level.change_game_time(0,hours,minutes) surge_manager.get_surge_manager().time_forwarded = true printf("traveling: time forwarded on [%d][%d]", hours, minutes) end if time_global() - init_time < 6000 then return end init_time = nil traveler_actor_path = nil traveler_squad_path = nil traveler_squad = nil traveler_distance = nil traveler_smart_id = nil bind_stalker.travel_func = nil level.show_weapon(true) --get_console():execute("hud_weapon 1") level.enable_input() level.show_indicators() end function squad_action_description(actor, npc, dialog_id, phrase_id) local npc_squad = get_object_squad(npc) if npc_squad.current_action == nil or npc_squad.current_action.name == "stay_point" then return "dm_" .. "stalker" .."_doing_nothing_"..tostring(math.random(1,3)) --npc:character_community() end local target_id = npc_squad.assigned_target_id -- if target_id == nil then -- return "dm_" .. npc:character_community() .."_doing_nothing" -- end local target_obj = alife():object(target_id) if target_obj == nil then abort("SIM TARGET NOT EXIST %s, action_name %s", tostring(target_id), tostring(npc_squad.current_action.name)) end local target_clsid = target_obj:clsid() if target_clsid == clsid.script_actor then abort("Actor talking with squad, which chasing actor") elseif target_clsid == clsid.online_offline_group_s then return "dm_" .. "stalker" .."_chasing_squad_"..alife_character_community(target_obj) --npc:character_community() elseif target_clsid == clsid.smart_terrain then local smart_name = target_obj:name() local travel_class = get_travel_class() local desc = travel_class.smart_to_stringtables[smart_name] if desc == nil then abort("wrong smart name [%s] in travel_manager.ltx", tostring(smart_name)) end return desc end abort("wrong target clsid [%s]", tostring(target_clsid)) end function squad_on_move(actor, npc, dialog_id, phrase_id) local npc_squad = get_object_squad(npc) if npc_squad.current_action == nil or npc_squad.current_action.name == "stay_point" then return false end return true end function squad_can_take_actor(npc, actor, dialog_id, phrase_id) local npc_squad = get_object_squad(npc) local target_id = npc_squad.assigned_target_id local target_obj = alife():object(target_id) local target_clsid = target_obj:clsid() if target_clsid == clsid.smart_terrain then return true end return false end function squad_cannot_take_actor(npc, actor, dialog_id, phrase_id) return not squad_can_take_actor(npc, actor, dialog_id, phrase_id) end function actor_go_with_squad(actor, npc, dialog_id, phrase_id) xr_effects.scenario_autosave(actor, npc, {"st_save_uni_travel_generic"}) local npc_squad = get_object_squad(npc) local target_id = npc_squad.assigned_target_id local smart = alife():object(target_id) npc:stop_talk() --get_console():execute("hud_crosshair 0") --get_console():execute("hud_weapon 0") level.disable_input() level.hide_indicators_safe() level.add_pp_effector("fade_in_out.ppe", 613, false) local distance = simulation_objects.sim_dist_to(npc_squad , smart) traveler_distance = distance traveler_actor_path = smart.traveler_actor_path traveler_squad_path = smart.traveler_squad_path traveler_smart_id = smart.id traveler_squad = npc_squad bind_stalker.travel_func = traveling init_time = time_global() teleport_flag = false end function check_smart_availability(smart_name, smart_table, squad) local board = sim_board.get_sim_board() local smart = board:get_smart_by_name(smart_name) if smart == nil then abort("Error in travel manager. Smart [%s] doesnt exist.", tostring(smart_name)) end if xr_logic.pick_section_from_condlist(db.actor, smart, smart_table.condlist) ~= "true" then return false end -- Проверка на текущий левел if smart_table.level ~= level.name() then return false end -- Мы не водим в текущий смарт if simulation_objects.sim_dist_to(squad , smart) < 50 then return false end -- local squad_count = smart_terrain.smart_terrain_squad_count(board.smarts[smart.id].squads) -- if squad_count ~= nil and (smart.max_population <= squad_count) then -- return false -- end return true end function squad_can_travel(npc, actor, dialog_id, phrase_id) local travel_class = get_travel_class() local npc_squad = get_object_squad(npc) for id, smart_table in pairs(travel_class.smart_travels) do if check_smart_availability(id, smart_table, npc_squad) then return true end end return false end function squad_cannot_travel(npc, actor, dialog_id, phrase_id) return not squad_can_travel(npc, actor, dialog_id, phrase_id) end function travel_condlist(actor, npc, dialog_id, prev_phrase_id, phrase_id) local travel_class = get_travel_class() -- Берем по id фразы смарт local smart_name = travel_class.smart_by_phrase[phrase_id] if smart_name == nil then abort("Error in travel manager %s", tostring(phrase_id)) end return check_smart_availability(smart_name, travel_class.smart_travels[smart_name], get_object_squad(npc)) end function get_price_by_distance(distance) return math.ceil(distance/50)*50 end function get_travel_cost(actor, npc, dialog_id, phrase_id, p1) local travel_phrase_id = string.sub(phrase_id, 1, string.len(phrase_id) - 2) local travel_class = get_travel_class() -- Берем по id фразы смарт local smart_name = travel_class.smart_by_phrase[travel_phrase_id] local board = sim_board.get_sim_board() local smart = board:get_smart_by_name(smart_name) local npc_squad = get_object_squad(npc) --local distance = simulation_objects.sim_dist_to(npc_squad , smart) local squad_position = npc:position() local smart_position = smart.position local distance = squad_position:distance_to(smart_position) local price = get_price_by_distance(distance) --printf("TRAVEL DISTANCE %s", distance) return game.translate_string("dm_traveler_travel_cost") .. " " .. tostring(price) .."." end function actor_have_money(actor, npc, dialog_id, phrase_id) local travel_phrase_id = string.sub(phrase_id, 1, string.len(phrase_id) - 2) local travel_class = get_travel_class() -- Берем по id фразы смарт local smart_name = travel_class.smart_by_phrase[travel_phrase_id] local board = sim_board.get_sim_board() local smart = board:get_smart_by_name(smart_name) local npc_squad = get_object_squad(npc) --local distance = simulation_objects.sim_dist_to(npc_squad , smart) local squad_position = npc:position() local smart_position = smart.position local distance = squad_position:distance_to(smart_position) local price = get_price_by_distance(distance) return price <= db.actor:money() end function actor_have_not_money(actor, npc, dialog_id, phrase_id) return not actor_have_money(actor, npc, dialog_id, phrase_id) end function actor_travel_with_squad(actor, npc, dialog_id, phrase_id) xr_effects.scenario_autosave(actor, npc, {"st_save_uni_travel_generic"}) local travel_phrase_id = string.sub(phrase_id, 1, string.len(phrase_id) - 3) local travel_class = get_travel_class() npc:stop_talk() --get_console():execute("hud_crosshair 0") --get_console():execute("hud_weapon 0") level.disable_input() level.hide_indicators_safe() level.add_pp_effector("fade_in_out.ppe", 613, false) -- Берем по id фразы смарт local smart_name = travel_class.smart_by_phrase[travel_phrase_id] local board = sim_board.get_sim_board() local smart = board:get_smart_by_name(smart_name) local npc_squad = get_object_squad(npc) local distance = simulation_objects.sim_dist_to(npc_squad , smart) local price = get_price_by_distance(distance) db.actor:give_money(-price) news_manager.relocate_money(db.actor, "out", price) traveler_actor_path = smart.traveler_actor_path traveler_squad_path = smart.traveler_squad_path traveler_smart_id = smart.id traveler_squad = npc_squad traveler_distance = distance bind_stalker.travel_func = traveling init_time = time_global() teleport_flag = false end