-- ///////////////////////// general ///////////////////////// local HI = has_alife_info local GI = give_info local DI = disable_info local gt = game.translate_string local ctime_to_t = utils_data.CTime_to_table local t_to_ctime = utils_data.CTime_from_table local redemption_3_start_time local redemption_4_start_time local redemption_4_aggro_time local redemption_5_start_time local redemption_end_items_found = 0 local debug_unlock_labs = false local allowed_storyline_factions = { ["stalker"] = true, ["csky"] = true, ["dolg"] = false, ["ecolog"] = false, ["freedom"] = false, ["army"] = false, ["killer"] = false, ["bandit"] = false, ["renegade"] = false, ["greh"] = false, ["isg"] = false, } function redemption_faction_precondition() if allowed_storyline_factions[get_actor_true_community()] then return true end end function redemption_unlock_bunker_route() if redemption_faction_precondition() then GI("redemption_6_unlock_bunker_route") redemption_open_route("prom", "bunk") end end function redemption_unlock_collider_route() if redemption_faction_precondition() then GI("redemption_6_unlock_collider_route") redemption_open_route("prom", "col") end end function redemption_open_route(map1, map2) if (not txr_routes.is_route_discovered(map1, map2)) then txr_routes.open_route(map1, map2) end end function redemption_goodwill_gain(comm, gw) if not (comm and gw) then return end relation_registry.change_community_goodwill(comm, 0, math.ceil(gw)) news_manager.send_tip(db.actor, string.format(gt("st_redemption_goodwill"), gt("st_faction_" .. comm)), 0, nil, 7500) end xr_conditions.npc_is_companion = function(a, npc, p) if npc and npc.alive and npc:alive() and p[1] and npc.section and npc:section() == p[1] and npc:has_info("npcx_is_companion") then return true end end xr_effects.redemption_send_text = function(a, b, p) local se_npc = p[2] and get_story_se_object(p[2]) if not (p[1] and p[3] and se_npc and se_npc.alive and se_npc:alive()) then return end local msg if p[3] == "task_1_eco" then local t = { [3] = "st_redemption_1_zero_more", [2] = "st_redemption_1_one_more", [1] = "st_redemption_1_two_more" } msg = t[p[1]] end if not msg then return end dynamic_news_helper.send_tip(gt(msg), se_npc:character_name(), nil, 10, se_npc:character_icon(), "beep_1", "npc") end function get_story_squad_id(story_id, ret_obj) local squad = get_story_squad(story_id) if squad and squad.commander_id then return ret_obj and squad or squad.id end end function get_story_se_id(story_id, ret_obj) local se_obj = get_story_se_object(story_id) if se_obj then return ret_obj and se_obj or se_obj.id end end function redemption_spawn_squad_on_smart(smart_name, squad_sec) local smart = SIMBOARD.smarts_by_names[smart_name] local squad = smart and SIMBOARD:create_squad(smart, squad_sec) if squad then sim_offline_combat.task_squads[squad.id] = true return squad end end function redemption_release_squad(story_id) local squad = get_story_squad_id(story_id, true) if squad and squad.commander_id then -- does not look reliable to let sim_offline_combat script do that with its 30 sec updates sim_offline_combat.task_squads[squad.id] = nil SIMBOARD:remove_squad(squad) end end function redemption_release_npc(story_id) local se_obj = story_id and get_story_se_object(story_id) if not se_obj then return end se_obj:kill() safe_release_manager.release(se_obj) end function redemption_release_sim_squads_on_smart(smart_name) local smart = smart_name and SIMBOARD.smarts_by_names[smart_name] if not (smart and SIMBOARD.smarts and SIMBOARD.smarts[smart.id] and SIMBOARD.smarts[smart.id].squads) then return end for id, _ in pairs(SIMBOARD.smarts[smart.id].squads) do local squad = alife_object(id) if squad and squad.commander_id and (string.find(squad:section_name(), "sim_squad") or string.find(squad:section_name(), "simulation_")) then SIMBOARD:remove_squad(squad) end end end function redemption_set_squad_position(sq, lvid) local squad_id = sq and sq.id if not squad_id then return end CreateTimeEvent("redemption_set_squad_pos_e_" .. squad_id, "redemption_set_squad_pos_a_" .. squad_id, 0.5, function(id) local squad = id and alife_object(id) if squad and squad.commander_id then for m in squad:squad_members() do local obj = level.object_by_id(m.id) local pos = obj and level.vertex_position(lvid) if pos then obj:set_npc_position(pos) end end end return true end, squad_id) end function redemption_pda_news(msg, obj_header, obj, delay, ttl, snd) if not obj then return end -- false or nil - default if not obj_header then obj_header = gt("st_tip") -- string - translated string elseif type(obj_header) == "string" then obj_header = gt(obj_header) -- true - obj name elseif obj_header == true then obj_header = obj:character_name() end snd = snd or "pda_tips" dynamic_news_helper.send_tip(gt(msg), obj_header, delay, ttl, obj:character_icon(), snd, "npc") end xr_effects.redemption_effects = function(a, npc, p) -- p[1] = type; p[2] = name; p[3] = id; p[4] = loop if not (p[1] and p[2] and p[3] and p[4]) then return end local p_bool = (p[4] == "true" and true) or (p[4] == "false" and false) if p_bool == nil then return end if p[1] == "anm" then level.add_cam_effector("camera_effects\\" .. p[2] .. ".anm", p[3], p_bool, "") elseif p[1] == "ppe" then level.add_pp_effector(p[2] .. ".ppe", p[3], p_bool) end end xr_effects.redemption_hit_obj = function(actor, npc, p) -- vanilla has incorrect direction local h = hit() local obj = get_story_object(p[1]) if not obj then return end h:bone(p[2]) h.power = p[3] h.impulse = p[4] local sid = p[5] and get_story_object(p[5]) if sid then h.direction = vec_sub(obj:position(), sid:position()) else h.direction = vec_sub(obj:position(), npc:position()) end h.draftsman = sid or npc h.type = hit.fire_wound obj:hit(h) end xr_effects.redemption_play_snd = function(a, npc, p) local idx = p[2] and math.random(1, p[2]) or "" local path = p[1] and p[1] .. idx local snd = path and sound_object(path) if snd and npc then snd:play_no_feedback(npc, sound_object.s3d, 0, npc:position(), 1, 1) end end xr_effects.redemption_play_snd_at_pos = function(a, npc, p) local snd = p[1] and sound_object(p[1]) local pos = VEC_ZERO if p[2] then pos = p[2] ~= 0 and level.vertex_position(p[2]) or pos end if snd and pos then local vol = p[3] or 1 snd:play_no_feedback(db.actor, sound_object.s2d, 0, pos, vol, 1) end end xr_conditions.redemption_dist_to_actor = function(a, npc, p) if npc and npc.alive and npc:alive() and p[1] then local dist_to = db.actor:position():distance_to(npc:position()) if dist_to and dist_to < p[1] then return true end end end -- ///////////////////////// 1 (start, protect scientist) ///////////////////////// function give_redemption_task_1() task_manager.get_task_manager():give_task("redemption_task_1") end local task_1_targets = { [4] = "prom_15", [3] = "prom_10", [2] = "prom_6" } task_functor.redemption_1_target_functor = function(task_id,field,p,tsk) local stage = tsk and tsk.stage if (field == "title") then return gt("st_redemption_task_1_title") elseif (field == "descr") then return stage and gt("st_redemption_task_1_descr_" .. stage) or gt("st_redemption_task_1_descr_0") elseif (field == "target") and stage then if (task_1_targets[stage]) then local smart = SIMBOARD.smarts_by_names[task_1_targets[stage]] return smart and smart.id elseif stage == 6 then return get_story_squad_id("yan_stalker_sakharov_squad") elseif stage == 5 then return get_story_squad_id("redemption_task_1_eco_squad") elseif stage == 1 then local restr = get_story_se_object("redemption_dummy_target") return restr and restr.id end end end task_status_functor.redemption_1_status_functor = function(tsk,task_id) if not tsk then return end if not tsk.stage then tsk.stage = 0 end -- fails are in ltx if HI("redemption_1_stage_6") then tsk.stage = 6 -- return to sakharov return elseif HI("redemption_1_stage_5") then tsk.stage = 5 -- talk to scientist return elseif HI("redemption_1_stage_4") then tsk.stage = 4 -- scan 3 return elseif HI("redemption_1_stage_3") then tsk.stage = 3 -- scan 2 return elseif HI("redemption_1_stage_2") then tsk.stage = 2 -- scan 1 return elseif HI("redemption_1_stage_1") then tsk.stage = 1 -- talk to scientist return end end function redemption_1_unlock_mil_prom() redemption_open_route("mil", "prom") end function redemption_1_spawn_scientist() redemption_spawn_squad_on_smart("prom_8", "redemption_task_1_eco_squad") end function redemption_1_release_scientist() redemption_release_squad("redemption_task_1_eco_squad") end function redemption_1_spawn_target() alife_create("redemption_dummy_target", vector():set(-420.5, -28.62, 66.5), 6283, 5415) end function redemption_1_release_target() local restr = get_story_se_object("redemption_dummy_target") if restr then alife_release(restr) end end xr_conditions.redemption_1_scan_2 = function(a, npc, p) if not (HI("redemption_1_stage_2")) then return end local smart = SIMBOARD.smarts_by_names["prom_6"] if smart and npc:position():distance_to(smart.position) < 15 then return true end end xr_conditions.redemption_1_scan_3 = function(a, npc, p) if not (HI("redemption_1_stage_3")) then return end local smart = SIMBOARD.smarts_by_names["prom_10"] if smart and npc:position():distance_to(smart.position) < 15 then return true end end xr_conditions.redemption_1_scan_4 = function(a, npc, p) if not (HI("redemption_1_stage_4")) then return end local smart = SIMBOARD.smarts_by_names["prom_15"] if smart and npc:position():distance_to(smart.position) < 15 then return true end end function redemption_1_give_reward(a, b) local num = 10000 dialogs.relocate_money_to_actor(a, b, num) end function redemption_1_give_goodwill() redemption_goodwill_gain("ecolog", 100) end function sakharov_1_1_text() return HI("redemption_1_dialogue_info") and gt("st_redemption_1_sakharov_11") or gt("st_redemption_1_sakharov_7") end function end_redemption_task_1() task_manager.get_task_manager():set_task_completed("redemption_task_1") end -- ///////////////////////// 2 (find documents) ///////////////////////// function give_redemption_task_2() task_manager.get_task_manager():give_task("redemption_task_2") end task_functor.redemption_2_target_functor = function(task_id,field,p,tsk) local stage = tsk and tsk.stage if (field == "title") then return gt("st_redemption_task_2_title") elseif (field == "descr") then return stage and gt("st_redemption_task_2_descr_" .. stage) or gt("st_redemption_task_2_descr_0") elseif (field == "target") and stage then if stage == 6 then local actor_has_docs = db.actor:object("redemption_2_documents") local docs_se_obj = get_story_se_item("redemption_2_documents") return (actor_has_docs and get_story_squad_id("yan_stalker_sakharov_squad")) or (docs_se_obj and docs_se_obj.id) elseif stage == 5 then local docs_se_obj = get_story_se_item("redemption_2_documents") return docs_se_obj and docs_se_obj.id elseif stage == 4 then return get_story_se_id("redemption_task_2_hare") elseif stage == 3 then local actor_has_vodka = db.actor:object("redemption_2_vodka_box") local vodka_se_obj = get_story_se_item("redemption_2_vodka_box") return (actor_has_vodka and get_story_squad_id("bar_visitors_barman_stalker_trader_squad")) or (vodka_se_obj and vodka_se_obj.id) elseif stage == 2 then return get_story_se_id("redemption_task_2_bandit") elseif stage == 1 then return get_story_squad_id("bar_visitors_barman_stalker_trader_squad") end end end task_status_functor.redemption_2_status_functor = function(tsk,task_id) if not tsk then return end if not tsk.stage then tsk.stage = 0 end -- if we take vodka box from dead body if redemption_2_actor_has_vodka_box() and HI("redemption_2_stage_2") and (not HI("redemption_2_stage_3")) then DI("redemption_2_stage_2") GI("redemption_2_stage_3") end -- if we take documents if redemption_2_actor_has_documents() and HI("redemption_2_stage_5") and (not HI("redemption_2_stage_6")) then DI("redemption_2_stage_5") GI("redemption_2_stage_6") redemption_2_release_hare() end if HI("redemption_2_stage_6") then tsk.stage = 6 -- bring documents to sakharov return elseif HI("redemption_2_stage_5") then tsk.stage = 5 -- get documents return elseif HI("redemption_2_stage_4") then tsk.stage = 4 -- talk to hare return elseif HI("redemption_2_stage_3") then tsk.stage = 3 -- bring vodka to barman return elseif HI("redemption_2_stage_2") then tsk.stage = 2 -- get vodka return elseif HI("redemption_2_stage_1") then tsk.stage = 1 -- talk to barman return end end function redemption_2_unlock_bar_trc() redemption_open_route("bar", "trc") end function redemption_2_spawn_bandit() alife_create("redemption_task_2_bandit", vector():set(-317.5, 18.85, -85.3), 15059, 5263) end function redemption_2_release_bandit() redemption_release_npc("redemption_task_2_bandit") end function redemption_2_relocate_vodka_box_to_actor(a, b) dialogs.relocate_item_section_to_actor(a, b, "redemption_2_vodka_box") end function redemption_2_bandit_enemy_eval(obj, enemy, flags) if not (HI("redemption_2_stage_2") or HI("redemption_2_stage_3")) then return end local bandit = get_story_object("redemption_task_2_bandit") if not (bandit and bandit.alive and bandit:alive()) then return end -- if hitted by actor if HI("redemption_2_bandit_attacked") then return end -- ignore combat local ignore if bandit:id() == obj:id() and (enemy:id() == 0 or enemy:has_info("npcx_is_companion")) then ignore = true elseif bandit:id() == enemy:id() and (obj:id() == 0 or obj:has_info("npcx_is_companion")) then ignore = true end if ignore then flags.override = true flags.result = false end end function redemption_2_bandit_before_hit(npc, s_hit, bone_id, flags) local se_bandit = get_story_se_object("redemption_task_2_bandit") local draft_actor = s_hit.draftsman and s_hit.draftsman:id() and s_hit.draftsman:id() == 0 if (se_bandit and se_bandit.id == npc:id()) and draft_actor then GI("redemption_2_bandit_attacked") end end function redemption_2_actor_has_vodka_box() return db.actor:object("redemption_2_vodka_box") end function redemption_2_relocate_vodka_box_to_barman(a, b) dialogs.relocate_item_section_from_actor(a, b, "redemption_2_vodka_box") end function redemption_2_give_vodka_to_actor(a, b) local amnt = ini_sys:r_float_ex("vodka2", "max_uses") or 3 dialogs.relocate_item_section_to_actor(a, b, "vodka2", amnt) end function redemption_2_give_goodwill_barman() redemption_goodwill_gain("dolg", 75) end function redemption_2_spawn_hare() alife_create("redemption_task_2_hare", vector():set(-222.5, -19.85, -163.7), 32970, 454) end function redemption_2_release_hare() redemption_release_npc("redemption_task_2_hare") end function redemption_2_actor_has_money() return db.actor:money() > 15000 end function redemption_2_actor_pay_money(a, b) local num = 15000 dialogs.relocate_money_from_actor(a, b, num) end function redemption_2_spawn_documents() alife_create("redemption_2_documents", vector():set(-80.602, 1.472, -49.555), 4294967295, 676) end function hare_1_text() return HI("redemption_2_dialogue_info") and gt("st_redemption_2_hare_1_1") or gt("st_redemption_2_hare_1") end function redemption_2_actor_has_documents() return db.actor:object("redemption_2_documents") end function redemption_2_relocate_documents_to_sakharov(a, b) dialogs.relocate_item_section_from_actor(a, b, "redemption_2_documents") end function redemption_2_give_reward(a, b) local num = 29000 dialogs.relocate_money_to_actor(a, b, num) end function redemption_2_give_goodwill_eco() redemption_goodwill_gain("ecolog", 125) end function end_redemption_task_2() task_manager.get_task_manager():set_task_completed("redemption_task_2") end -- ///////////////////////// 3 (station) ///////////////////////// function give_redemption_task_3() task_manager.get_task_manager():give_task("redemption_task_3") end task_functor.redemption_3_target_functor = function(task_id,field,p,tsk) local stage = tsk and tsk.stage if (field == "title") then return gt("st_redemption_task_3_title") elseif (field == "descr") then if stage then return stage ~= -1 and gt("st_redemption_task_3_descr_" .. stage) or gt("st_redemption_task_3_descr_comp") end return gt("st_redemption_task_3_descr_0") elseif (field == "target") and stage then if stage == 3 then return get_story_squad_id("yan_stalker_sakharov_squad") elseif stage == 2 then return get_story_se_id("redemption_task_3_hare") elseif stage == 1 then local restr = get_story_se_object("redemption_dummy_target") return restr and restr.id end end end task_status_functor.redemption_3_status_functor = function(tsk,task_id) if not tsk then return end if not tsk.stage then tsk.stage = 0 end -- leave companions for stage 1 if #axr_companions.list_actor_squad_by_id() > 0 and HI("redemption_3_stage_1") then tsk.stage = -1 return end if HI("redemption_3_stage_3") then tsk.stage = 3 -- go to sakharov return elseif HI("redemption_3_stage_2") then tsk.stage = 2 -- contact sakharov return elseif HI("redemption_3_stage_1") then tsk.stage = 1 -- place devices local ac_pos = db.actor:position() local eco = get_story_object("redemption_task_3_eco_1") local dist_to = eco and eco:position() and ac_pos:distance_to(eco:position()) if dist_to and dist_to < 15 and (not HI("redemption_3_found_ecos")) then -- if we found ecologists GI("redemption_3_found_ecos") redemption_3_found_eco() end return end end function redemption_3_start_timer() redemption_3_start_time = ctime_to_t(game.get_game_time()) end function redemption_3_check_timer() local time_diff = redemption_3_start_time and game.get_game_time():diffSec(t_to_ctime(redemption_3_start_time)) if time_diff and time_diff > 6600 then return true end end function redemption_3_spawn_dead_ecos() local eco_1 = alife_create("redemption_task_3_eco_1", vector():set(374.048, -17.0234, -263.611), 833158, 5482) local eco_2 = alife_create("redemption_task_3_eco_2", vector():set(374.753, -18.5022, -274.9857), 833919, 5482) if eco_1 then eco_1:kill() end if eco_2 then eco_2:kill() end end function redemption_3_found_eco() local se_sakharov = get_story_se_object("yan_stalker_sakharov") redemption_pda_news("st_redemption_3_ecos_1", true, db.actor, 4, 12) redemption_pda_news("st_redemption_3_ecos_2", true, se_sakharov, 9, 10) redemption_pda_news("st_redemption_3_ecos_3", true, db.actor, 14, 10) end function redemption_3_relocate_device_to_actor(a, b) dialogs.relocate_item_section_to_actor(a, b, "redemption_3_device") end function redemption_3_menu_place(item) return game.translate_string("st_item_place") end function redemption_3_use_place(obj) local p = obj and obj:parent() if not (p and p:id() == AC_ID) then return end local place_pos = vector():set(377.294, 3.3806, -272.506) local dist_to = db.actor:position():distance_to(place_pos) if not (dist_to and dist_to < 2) then redemption_pda_news("st_redemption_3_device_cant_place", true, db.actor, 0, 5) return end alife_release(obj) alife_create("redemption_3_device_obj", place_pos, 837931, 5482) local se_sakharov = get_story_se_object("yan_stalker_sakharov") redemption_pda_news("st_redemption_3_news_1", true, db.actor, 2, 12) redemption_pda_news("st_redemption_3_news_2", true, se_sakharov, 8, 10) GI("redemption_3_stage_2") DI("redemption_3_stage_1") redemption_3_release_target() redemption_3_spawn_hare() end function redemption_3_spawn_target() alife_create("redemption_dummy_target", vector():set(377.294, 3.3806, -272.506), 837931, 5482) end function redemption_3_release_target() local restr = get_story_se_object("redemption_dummy_target") if restr then alife_release(restr) end end function redemption_3_spawn_hare() alife_create("redemption_task_3_hare", vector():set(269.44, -22.21, -265.17), 706288, 5471) end function redemption_3_release_hare() redemption_release_npc("redemption_task_3_hare") end function redemption_3_spawn_monoliths() alife_create("redemption_task_3_monolith_1", vector():set(286.92, -22.063, -229.186), 730530, 5472) alife_create("redemption_task_3_monolith_2", vector():set(278.946, -21.914, -227.267), 719802, 5472) alife_create("redemption_task_3_monolith_3", vector():set(309.8, -22.113, -242.697), 761520, 5478) end function redemption_3_hide_weapon() level.show_weapon(false) end function redemption_3_show_weapon() level.show_weapon(true) end function redemption_3_disable_input_and_turn() level.disable_input() db.actor:actor_look_at_point(vector():set(287, -21, -229)) end xr_effects.redemption_3_lay_down = function() db.actor:set_actor_position(vector():set(273.152, -22.371, -263.999)) local dir = vector():set(-0.854564, -0.212816, 0.47374) db.actor:set_actor_direction(-dir:getH()) end xr_effects.redemption_3_draw_wallmarks = function() local hare = get_story_object("redemption_task_3_hare") local hare_old_pos = hare and hare:position() local hare_pos = hare_old_pos and vector():set(hare_old_pos.x, hare_old_pos.y + 1, hare_old_pos.z) if hare_pos then wallmarks_manager():place(vector():set(0, -1, 0), hare_pos, 10, 0.75, "redemption_wm_blood_" .. math.random(1, 6), hare, 600) wallmarks_manager():place(vector():set(0.249, 0.174, -0.953), hare_pos, 15, 0.75, "redemption_wm_blood_" .. math.random(1, 6), hare, 600) end local old_ac_pos = db.actor:position() local actor_pos = old_ac_pos and vector():set(old_ac_pos.x, old_ac_pos.y + 1, old_ac_pos.z) if actor_pos then wallmarks_manager():place(vector():set(0, -1, 0), actor_pos, 10, 0.75, "redemption_wm_blood_" .. math.random(1, 6), db.actor, 600) wallmarks_manager():place(vector():set(-0.225, -0.2, -0.953), actor_pos, 15, 0.75, "redemption_wm_blood_" .. math.random(1, 6), db.actor, 600) end end xr_effects.redemption_3_monolith_talk = function() local mono_leader = get_story_object("redemption_task_3_monolith_1") local mono_member = get_story_object("redemption_task_3_monolith_2") redemption_pda_news("st_redemption_3_monolith_news_1", "st_redemption_task_3_news_unknown", mono_member, 0, 6) redemption_pda_news("st_redemption_3_monolith_news_2", "st_redemption_task_3_news_unknown", mono_leader, 4, 6) end xr_effects.redemption_3_spawn_illeon = function() alife_create("redemption_task_3_illeon", vector():set(180.279, -21.701, -266.359), 575646, 5466) end xr_effects.redemption_3_release_bodies = function() redemption_release_npc("redemption_task_3_eco_1") redemption_release_npc("redemption_task_3_eco_2") redemption_release_npc("redemption_task_3_hare") for i = 1, 3 do redemption_release_npc("redemption_task_3_monolith_" .. i) end end xr_effects.redemption_3_teleport_to_subway = function() -- illeon_fade 2.5 level.remove_cam_effector(7774) -- remove lay down to set it again db.actor:set_actor_position(vector():set(521.2, -28.19, 149.718)) local dir = vector():set(-0.1384, -0.272, -0.95) db.actor:set_actor_direction(-dir:getH()) local illeon = get_story_object("redemption_task_3_illeon") illeon:set_npc_position(vector():set(515.088, -28.240, 142.986)) for i = 1, 4 do local function red_time_event(idx) level.change_game_time(0, 3, 0) db.actor:cast_Actor():conditions():ChangeSatiety(1) return true end CreateTimeEvent("redemption_3_change_time_e_" .. i, "redemption_3_change_time_a_" .. i, i/10, red_time_event, i) end surge_manager.get_surge_manager().time_forwarded = true psi_storm_manager.get_psi_storm_manager().time_forwarded = true level_weathers.get_weather_manager():forced_weather_change() end xr_effects.redemption_3_illeon_talk = function() -- illeon_teleport 4 level.add_pp_effector("fade_out.ppe", 7780, false) level.remove_pp_effector(7777) local illeon = get_story_object("redemption_task_3_illeon") redemption_pda_news("st_redemption_3_illeon_news_1", "st_redemption_task_3_news_unknown", illeon, 4, 6) redemption_pda_news("st_redemption_3_illeon_news_2", true, db.actor, 12, 6) redemption_pda_news("st_redemption_3_illeon_news_3", "st_redemption_task_3_news_unknown", illeon, 14, 6) redemption_pda_news("st_redemption_3_illeon_news_4", true, db.actor, 20, 6) end xr_effects.redemption_3_change_time = function() -- illeon_fade_2 1.5 for i = 1, 7 do local function red_time_event(idx) level.change_game_time(0, 3, 0) db.actor:cast_Actor():conditions():ChangeSatiety(1) return true end CreateTimeEvent("redemption_3_change_time_e_" .. i, "redemption_3_change_time_a_" .. i, i/10, red_time_event, i) end surge_manager.get_surge_manager().time_forwarded = true psi_storm_manager.get_psi_storm_manager().time_forwarded = true level_weathers.get_weather_manager():forced_weather_change() end xr_effects.redemption_3_remove_effectors = function() -- illeon_wake_up 4 level.remove_cam_effector(7778) for i = 7770, 7785 do level.remove_pp_effector(i) end level.add_pp_effector("fade_out.ppe", 7770, false) level.add_pp_effector("surge_shock_old.ppe", 7771, false) level.add_cam_effector("camera_effects\\prison_1.anm", 7772, false, "") disable_info("redemption_3_actor_invul") disable_info("redemption_3_cutscene_started") db.actor:set_health_ex(0.55) end xr_effects.redemption_3_enable_input = function() -- illeon_input 7 level.enable_input() end function redemption_3_respawn_illeon() level.disable_input() level.add_pp_effector("fade_in.ppe", 7770, false) CreateTimeEvent("redemption_3_illeon_respawn_e", "redemption_3_illeon_respawn_a", 0.5, function() redemption_release_npc("redemption_task_3_illeon") redemption_spawn_squad_on_smart("prom_7", "redemption_task_3_illeon_stalker_squad") return true end) end function redemption_3_release_illeon_squad() redemption_release_squad("redemption_task_3_illeon_stalker_squad") end function redemption_3_actor_before_hit(s_hit, bone_id, flags) if not (HI("redemption_3_cutscene_started")) then return end flags.ret_value = false end local red_3_tmr = 0 function redemption_3_health_update() if not (HI("redemption_3_actor_invul")) then return end if red_3_tmr > time_global() then return end red_3_tmr = time_global() + 50 db.actor.radiation = 0 db.actor.bleeding = 0 if db.actor.health > 0.11 then db.actor:set_health_ex(db.actor.health - 0.009) end end function sakharov_3_1_text() return HI("redemption_task_3_illeon_death") and gt("st_redemption_3_yantar_1_1") or gt("st_redemption_3_yantar_1") end function sakharov_3_5_text() return HI("redemption_task_3_illeon_death") and gt("st_redemption_3_yantar_5_1") or gt("st_redemption_3_yantar_5") end function redemption_3_give_reward(a, b) local num = 18000 dialogs.relocate_money_to_actor(a, b, num) end function redemption_3_give_goodwill() redemption_goodwill_gain("ecolog", 125) end function end_redemption_task_3() task_manager.get_task_manager():set_task_completed("redemption_task_3") end -- ///////////////////////// 4 () ///////////////////////// function give_redemption_task_4() task_manager.get_task_manager():give_task("redemption_task_4") end task_functor.redemption_4_target_functor = function(task_id,field,p,tsk) local stage = tsk and tsk.stage if (field == "title") then return gt("st_redemption_task_4_title") elseif (field == "descr") then return stage and gt("st_redemption_task_4_descr_" .. stage) or gt("st_redemption_task_4_descr_0") elseif (field == "target") and stage then if stage == 6 then return get_story_squad_id("yan_stalker_sakharov_squad") elseif stage == 5 then return get_story_squad_id("bar_visitors_barman_stalker_trader_squad") elseif stage == 4 then local smart = SIMBOARD.smarts_by_names["agr_smart_terrain_6_4"] return smart and smart.id elseif stage == 3 then return get_story_squad_id("bar_visitors_barman_stalker_trader_squad") elseif stage == 2 then local smart = SIMBOARD.smarts_by_names["val_smart_terrain_7_5"] return smart and smart.id elseif stage == 1 then return get_story_squad_id("bar_visitors_barman_stalker_trader_squad") end end end task_status_functor.redemption_4_status_functor = function(tsk,task_id) if not tsk then return end if not tsk.stage then tsk.stage = 0 end -- check for weapon in darkvalley local stage_check = (HI("redemption_4_stage_2") or HI("redemption_4_stage_3")) and (not HI("redemption_4_zombie_arena")) local has_weapon = redemption_4_actor_has_weapon() local has_comps = #axr_companions.list_actor_squad_by_id() > 0 if stage_check and (has_weapon or has_comps) then GI("redemption_4_has_wpn") else DI("redemption_4_has_wpn") end -- check if zombies are killed if HI("redemption_4_zombie_arena") and HI("redemption_task_4_zombies_killed") then DI("redemption_4_zombie_arena") redemption_4_end_arena() end -- if no aggro yet and stoves are lit - start aggro timer if (not HI("redemption_4_bandits_aggro")) and HI("redemption_4_stage_2") and (not redemption_4_aggro_time) then local se_fire = get_story_se_item("redemption_4_stoves_fire") local obj_fire = se_fire and level.object_by_id(se_fire.id) local obj_campfire = obj_fire and obj_fire:get_campfire() if obj_campfire and obj_campfire:is_on() then GI("redemption_4_beh_move") redemption_4_aggro_time = ctime_to_t(game.get_game_time()) end end -- if no aggro yet and timer exist - add time to aggro timer (and bandit talk) if (not HI("redemption_4_bandits_aggro")) and redemption_4_aggro_time then local time_diff = game.get_game_time():diffSec(t_to_ctime(redemption_4_aggro_time)) if time_diff then -- news dialogue local se_sultan = get_story_se_object("zat_b7_bandit_boss_sultan") local se_bandit = get_story_se_object("redemption_task_4_bandit_2") if time_diff > 360 then -- 60 sec DI("redemption_4_beh_move") GI("redemption_4_bandits_aggro") -- enable aggro elseif time_diff > 180 and (not HI("redemption_4_aggro_news_2")) then -- 30 sec GI("redemption_4_aggro_news_2") redemption_pda_news("st_redemption_4_sultan_news_4", true, se_sultan, 0, 12) redemption_pda_news("st_redemption_4_sultan_news_5", true, se_bandit, 10, 12) redemption_pda_news("st_redemption_4_sultan_news_6", true, se_sultan, 20, 15) elseif time_diff > 30 and (not HI("redemption_4_aggro_news_1")) then -- 5 sec GI("redemption_4_aggro_news_1") redemption_pda_news("st_redemption_4_sultan_news_1", true, se_sultan, 0, 12) redemption_pda_news("st_redemption_4_sultan_news_2", true, se_sultan, 10, 12) redemption_pda_news("st_redemption_4_sultan_news_3", true, se_bandit, 18, 12) end end end -- if actor picks up the documents if HI("redemption_4_stage_2") and (not HI("redemption_4_stage_3")) and redemption_4_actor_has_docs() then -- if picked without stoves or without killing zombies - instant aggro if not (redemption_4_aggro_time or HI("redemption_task_4_zombies_killed")) then GI("redemption_4_bandits_aggro") end redemption_4_release_fire() GI("redemption_4_stage_3") DI("redemption_4_stage_2") end -- actor picks up the documents from agroprom if HI("redemption_4_stage_4") and (not HI("redemption_4_stage_5")) and redemption_4_actor_has_agro_docs() then GI("redemption_4_stage_5") DI("redemption_4_stage_4") end if HI("redemption_4_stage_6") then tsk.stage = 6 -- talk to sakharov return elseif HI("redemption_4_stage_5") then tsk.stage = 5 -- bring documents to barman return elseif HI("redemption_4_stage_4") then tsk.stage = 4 -- get docs on agroprom return elseif HI("redemption_4_stage_3") then tsk.stage = 3 -- bring documents to barman return elseif HI("redemption_4_stage_2") then tsk.stage = 2 -- get documents return elseif HI("redemption_4_stage_1") then tsk.stage = 1 -- talk to barman return end end function redemption_4_start_timer() redemption_4_start_time = ctime_to_t(game.get_game_time()) end function redemption_4_check_timer() local time_diff = redemption_4_start_time and game.get_game_time():diffSec(t_to_ctime(redemption_4_start_time)) if time_diff and time_diff > 64800 then return true end end function redemption_4_actor_has_weapon() if level.name() ~= "l04_darkvalley" then return end local has_wpn = false local function itr(item) if IsWeapon(item) or IsGrenade(item) then has_wpn = true return true end end db.actor:inventory_for_each(itr) return has_wpn end function redemption_4_enemy_actor_or_zombie(enemy) if enemy:id() == 0 then return true end local squad = get_object_squad(enemy) if squad and squad.commander_id and squad:section_name() == "redemption_task_4_arena_zombie_squad" then return true end end function redemption_4_bandits_enemy_eval(obj, enemy, flags) if not (HI("redemption_4_stage_2") or HI("redemption_4_stage_3")) then return end if level.name() ~= "l04_darkvalley" then return end -- bandits to actor / zombies local comm = IsStalker(obj) and obj:character_community() local comm_bandit = comm and (comm == "bandit" or comm == "renegade") local enemy_actor_or_zombie = redemption_4_enemy_actor_or_zombie(enemy) if comm_bandit and enemy_actor_or_zombie and (not HI("redemption_4_bandits_aggro")) then -- zombie arena if HI("redemption_4_zombie_arena") then flags.override = true flags.result = false return end -- rest if not (HI("redemption_4_has_wpn")) then flags.override = true flags.result = false return end end -- zombies ignore everyone except actor if obj:id() ~= 0 then -- dont know if possible, but get_object_squad on actor breaks game local squad = get_object_squad(obj) local squad_check = squad and squad.commander_id and squad:section_name() == "redemption_task_4_arena_zombie_squad" if squad_check and enemy:id() ~= 0 then flags.override = true flags.result = false return end end end function redemption_4_bandits_before_hit(npc, s_hit, bone_id, flags) -- if we hit bandits in dark valley during these stages if not (HI("redemption_4_stage_2") or HI("redemption_4_stage_3")) then return end if level.name() ~= "l04_darkvalley" then return end local comm = npc:character_community() local comm_bandit = comm and (comm == "bandit" or comm == "renegade") local draft_actor = s_hit.draftsman and s_hit.draftsman:id() and s_hit.draftsman:id() == 0 if comm_bandit and draft_actor then GI("redemption_4_bandits_aggro") end end function redemption_4_actor_has_money() return db.actor:money() > 4000 end function redemption_4_actor_pay_money(a, b) local num = 4000 dialogs.relocate_money_from_actor(a, b, num) end function redemption_4_unlock_gar_val() redemption_open_route("gar", "val") end function redemption_4_spawn_docs_fire() alife_create("redemption_4_documents", vector():set(41.7, 5.44, -84.494), 214289, 1648) local se_fire = alife_create("redemption_4_stoves_fire", vector():set(48.944, 1.5, -51.49), 222786, 1651) local data = se_fire and utils_stpk.get_anom_zone_data(se_fire) if data then data.shapes[1] = {} data.shapes[1].shtype = 0 data.shapes[1].offset = vector():set(0, 0, 0) data.shapes[1].center = vector():set(0, 1, 0) data.shapes[1].radius = 0.75 utils_stpk.set_anom_zone_data(data, se_fire) end end function redemption_4_release_fire() -- destroy stoves fire anomaly coz we choose different path local se_fire = get_story_se_item("redemption_4_stoves_fire") local obj_fire = se_fire and level.object_by_id(se_fire.id) if obj_fire then bind_campfire.campfires_all[se_fire.id] = nil obj_fire:destroy_object() end end function redemption_4_spawn_bandits() alife_create("redemption_task_4_bandit_1", vector():set(19.972, 4.542, -84.05), 189090, 1647) alife_create("redemption_task_4_bandit_2", vector():set(39.134, 1.0226, -52.8732), 210821, 1644) end function redemption_4_release_bandits() redemption_release_npc("redemption_task_4_bandit_1") redemption_release_npc("redemption_task_4_bandit_2") end function redemption_4_start_arena() level.disable_input() level.add_pp_effector("fade_in.ppe", 7771, false) -- despawn fire coz we choose different path redemption_4_release_fire() -- blocking local block_pos_t = { [1] = 34.5, [2] = 36.1, [3] = 37.7 } for i = 1, 3 do local block_pos = vector():set(block_pos_t[i], 1, -47) local se_obj = alife_create("redemption_4_basement_block_" .. i, block_pos, 217872, 1641) if se_obj then se_obj.angle = vector():set(-1.57, 1.57, 1.57) end end -- actor pos/dir db.actor:set_actor_position(vector():set(40.448, -2.498, -54.585), 212647, 1641) local dir = vector():set(0.026, -0.218, 0.9756) db.actor:set_actor_direction(-dir:getH()) -- inv_box / transfer / give knife local se_inv = alife_create("redemption_4_inv_box", vector():set(24.37, 0.11, -50.9), 193741, 1632) CreateTimeEvent("redemption_4_transfer_from_e", "redemption_4_transfer_from_a", 0.5, function() local se_inv_box = get_story_se_object("redemption_4_inv_box") local obj_inv_box = se_inv_box and level.object_by_id(se_inv_box.id) if obj_inv_box then local function transfer_to_box(item) db.actor:transfer_item(item, obj_inv_box) end db.actor:inventory_for_each(transfer_to_box) end return true end) -- spawn zombies local zombie_squad = redemption_spawn_squad_on_smart("val_smart_terrain_7_5", "redemption_task_4_arena_zombie_squad") CreateTimeEvent("redemption_4_tp_zombie_e", "redemption_4_tp_zombie_a", 0.5, function(squad_id) local sq = squad_id and alife_object(squad_id) if sq and sq.commander_id then for m in sq:squad_members() do local obj_zombie = level.object_by_id(m.id) local zombie_pos = obj_zombie and level.vertex_position(210046) if zombie_pos then obj_zombie:set_npc_position(zombie_pos) end end end return true end, zombie_squad and zombie_squad.id) -- enable input and spawn knife CreateTimeEvent("redemption_4_arena_input_e", "redemption_4_arena_input_a", 2, function() alife_create_item("wpn_knife", db.actor) level.enable_input() return true end) end function redemption_4_end_arena() level.add_pp_effector("fade_in.ppe", 7772, false) -- remove blocking for i = 1, 3 do local se_obj = get_story_se_item("redemption_4_basement_block_" .. i) if se_obj then alife_release(se_obj) end end -- transfer back / remove inv_box local se_inv_box = get_story_se_item("redemption_4_inv_box") local obj_inv_box = se_inv_box and level.object_by_id(se_inv_box.id) if obj_inv_box then local function transfer_from_box(box,item) box:transfer_item(item, db.actor) end obj_inv_box:iterate_inventory_box(transfer_from_box, obj_inv_box) end alife_release(se_inv_box) -- take knife local function itr(item) if item:section() == "wpn_knife" then alife_release(item) end end db.actor:inventory_for_each(itr) end function sultan_1_1_text() return HI("redemption_4_sultan_fight_dialogue") and gt("st_redemption_4_sultan_11_1") or gt("st_redemption_4_sultan_1") end function redemption_4_actor_has_docs() return db.actor:object("redemption_4_documents") end function redemption_4_relocate_docs_to_barman(a, b) dialogs.relocate_item_section_from_actor(a, b, "redemption_4_documents") end function redemption_4_give_reward_docs(a, b) local num = 14000 dialogs.relocate_money_to_actor(a, b, num) end function redemption_4_give_goodwill_docs() redemption_goodwill_gain("ecolog", 100) end function redemption_4_spawn_bloodsuckers() redemption_spawn_squad_on_smart("agr_smart_terrain_6_4", "redemption_task_4_bloodsucker_squad") end function redemption_4_spawn_dead_stalkers() local stalker_1 = alife_create("redemption_task_4_stalker_1", vector():set(242.9, 0.9579, 65.1), 400398, 1031) local stalker_2 = alife_create("redemption_task_4_stalker_2", vector():set(253.4, 0.8322, 70), 408169, 1031) if stalker_1 then stalker_1:kill() end if stalker_2 then stalker_2:kill() CreateTimeEvent("redemption_4_delay_agro_docs_e", "redemption_4_delay_agro_docs_a", 1, function(id) local sobj = alife_object(id) if sobj then alife_create_item("redemption_4_agro_documents", sobj) end return true end, stalker_2.id) end end function redemption_4_release_bloodsuckers() redemption_release_squad("redemption_task_4_bloodsucker_squad") end function redemption_4_release_dead_stalkers() redemption_release_npc("redemption_task_4_stalker_1") redemption_release_npc("redemption_task_4_stalker_2") end function redemption_4_unlock_gar_agr() redemption_open_route("gar", "agr") end function redemption_4_release_agro_sim_squads() redemption_release_sim_squads_on_smart("agr_smart_terrain_6_4") end function redemption_4_actor_has_agro_docs() return db.actor:object("redemption_4_agro_documents") end function redemption_4_relocate_agro_docs_to_barman(a, b) dialogs.relocate_item_section_from_actor(a, b, "redemption_4_agro_documents") end function redemption_4_give_reward_agro_docs(a, b) local num = 19000 dialogs.relocate_money_to_actor(a, b, num) end function redemption_4_give_goodwill_agro_docs() redemption_goodwill_gain("stalker", 100) end function end_redemption_task_4() task_manager.get_task_manager():set_task_completed("redemption_task_4") end -- ///////////////////////// 5 () ///////////////////////// function give_redemption_task_5() task_manager.get_task_manager():give_task("redemption_task_5") end task_functor.redemption_5_target_functor = function(task_id,field,p,tsk) local stage = tsk and tsk.stage if (field == "title") then return gt("st_redemption_task_5_title") elseif (field == "descr") then return stage and gt("st_redemption_task_5_descr_" .. stage) or gt("st_redemption_task_5_descr_0") elseif (field == "target") and stage then if stage == 7 then return get_story_squad_id("bar_visitors_barman_stalker_trader_squad") elseif stage == 6 then local smart = SIMBOARD.smarts_by_names["mil_smart_terrain_7_4"] return smart and smart.id elseif stage == 5 then return get_story_squad_id("bar_dolg_leader_squad") elseif stage == 4 then return get_story_squad_id("mil_smart_terrain_7_7_freedom_leader_stalker_squad") elseif stage == 3 then return get_story_squad_id("redemption_task_5_snorks_squad") elseif stage == 2 then return get_story_squad_id("mil_smart_terrain_7_7_freedom_leader_stalker_squad") elseif stage == 1 then return get_story_squad_id("bar_dolg_leader_squad") end end end task_status_functor.redemption_5_status_functor = function(tsk,task_id) if not tsk then return end if not tsk.stage then tsk.stage = 0 end -- snorks killed if HI("redemption_5_stage_3") and HI("redemption_task_5_snorks_killed") then GI("redemption_5_stage_4") DI("redemption_5_stage_3") end if HI("redemption_5_stage_7") then tsk.stage = 7 -- talk to barman return elseif HI("redemption_5_stage_6") then tsk.stage = 6 -- go to meeting return elseif HI("redemption_5_stage_5") then tsk.stage = 5 -- talk to voronin return elseif HI("redemption_5_stage_4") then tsk.stage = 4 -- talk to lukash return elseif HI("redemption_5_stage_3") then tsk.stage = 3 -- kill mutants return elseif HI("redemption_5_stage_2") then tsk.stage = 2 -- talk to lukash return elseif HI("redemption_5_stage_1") then tsk.stage = 1 -- talk to voronin return end end function redemption_5_start_timer() redemption_5_start_time = ctime_to_t(game.get_game_time()) end function sakharov_5_1_1_text() local time_diff = redemption_5_start_time and game.get_game_time():diffSec(t_to_ctime(redemption_5_start_time)) if HI("redemption_5_skip_start_timer") then return gt("st_redemption_5_sakharov_2_1") elseif time_diff then if time_diff >= 259200 then return gt("st_redemption_5_sakharov_2_1") elseif time_diff > 172800 then return gt("st_redemption_5_sakharov_2_2") elseif time_diff > 86400 then return gt("st_redemption_5_sakharov_2_3") else return gt("st_redemption_5_sakharov_2_4") end end end function redemption_5_check_timer() local time_diff = redemption_5_start_time and game.get_game_time():diffSec(t_to_ctime(redemption_5_start_time)) if HI("redemption_5_skip_start_timer") or (time_diff and time_diff >= 259200) then return true end end function redemption_5_release_prom_sim_squads() redemption_release_sim_squads_on_smart("prom_1") redemption_release_sim_squads_on_smart("prom_2") redemption_release_sim_squads_on_smart("prom_3") redemption_release_sim_squads_on_smart("prom_4") end function redemption_5_spawn_monolith() for i = 1, 4 do redemption_spawn_squad_on_smart("prom_1", "redemption_task_5_monolith_squad_" .. i) end end function redemption_5_spawn_illeon() redemption_spawn_squad_on_smart("yan_smart_terrain_6_4", "redemption_task_5_illeon_squad") end function redemption_5_unlock_mil_grim() redemption_open_route("mil", "grim") end function redemption_5_release_grim_sim_squads() redemption_release_sim_squads_on_smart("grim_9") end function redemption_5_spawn_snorks() redemption_spawn_squad_on_smart("grim_9", "redemption_task_5_snorks_squad") end function redemption_5_spawn_dutier_comp() local se_obj = redemption_spawn_squad_on_smart("mil_smart_terrain_7_7", "redemption_task_5_dutier_squad") if se_obj then CreateTimeEvent("redemption_5_delay_dutier_e", "redemption_5_delay_dutier_a", 1, function(id) local squad = alife_object(id) if squad and squad.commander_id then axr_companions.companion_squads[squad.id] = squad SIMBOARD:assign_squad_to_smart(squad, nil) for k in squad:squad_members() do local member = k and level.object_by_id(k.id) if member and member:alive() then axr_companions.add_to_actor_squad(member) end end end return true end, se_obj.id) end end function redemption_5_give_goodwill_freedom() redemption_goodwill_gain("freedom", 125) end function redemption_5_ignore_dutier(obj, enemy, flags) if not (HI("redemption_5_stage_5")) then return end local obj_comm = obj:character_community() local en_comm = enemy:character_community() if not (obj_comm and en_comm) then return end local obj_dutier = obj:section() == "redemption_task_5_dutier" and en_comm == "freedom" local en_dutier = enemy:section() == "redemption_task_5_dutier" and obj_comm == "freedom" if obj_dutier or en_dutier then flags.override = true flags.result = false end end function redemption_5_dutier_near_and_alive() if HI("redemption_5_stage_5") and (not HI("redemption_task_5_dutier_death")) then local obj = get_story_object("redemption_task_5_dutier") if obj and obj.alive and obj:alive() and obj:has_info("npcx_is_companion") then return true end end end function redemption_5_release_dutier() redemption_release_squad("redemption_task_5_dutier_squad") end function redemption_5_release_mil_sim_squads() redemption_release_sim_squads_on_smart("mil_smart_terrain_7_4") redemption_release_sim_squads_on_smart("mil_smart_terrain_8_3") end function redemption_5_spawn_duty_freedom() alife_create("redemption_task_5_duty_captain", vector():set(-230.3, -11.643, 44.1), 94154, 2167) alife_create("redemption_task_5_duty_1", vector():set(-231.7, -11.643, 42), 93035, 2167) alife_create("redemption_task_5_freedom_captain", vector():set(-226.8, -11.6548, 44.1), 96838, 2167) alife_create("redemption_task_5_freedom_1", vector():set(-224, -11.643, 42.7), 99122, 2167) end function redemption_5_give_goodwill_duty() redemption_goodwill_gain("dolg", 125) end function redemption_5_duty_freedom_enemy_eval(obj, enemy, flags) if not (HI("redemption_5_stage_6") or HI("redemption_5_stage_7")) then return end local obj_comm = IsStalker(obj) and obj:character_community() local en_comm = IsStalker(enemy) and enemy:character_community() if not (obj_comm and en_comm) then return end local duty_freed = obj_comm == "dolg" and en_comm == "freedom" local freed_duty = obj_comm == "freedom" and en_comm == "dolg" if duty_freed or freed_duty then flags.override = true flags.result = false end end function redemption_5_release_duty_freedom() level.add_pp_effector("fade_in.ppe", 7770, false) CreateTimeEvent("redemption_5_release_squads_e", "redemption_5_release_squads_a", 1, function() redemption_release_npc("redemption_task_5_duty_captain") redemption_release_npc("redemption_task_5_duty_1") redemption_release_npc("redemption_task_5_freedom_captain") redemption_release_npc("redemption_task_5_freedom_1") return true end) end function end_redemption_task_5() task_manager.get_task_manager():set_task_completed("redemption_task_5") end -- ///////////////////////// 6 () ///////////////////////// function give_redemption_task_6() task_manager.get_task_manager():give_task("redemption_task_6") end task_functor.redemption_6_target_functor = function(task_id,field,p,tsk) local stage = tsk and tsk.stage if (field == "title") then return gt("st_redemption_task_6_title") elseif (field == "descr") then return stage and gt("st_redemption_task_6_descr_" .. stage) or gt("st_redemption_task_6_descr_0") elseif (field == "target") and stage then if stage == 6 then return get_story_squad_id("yan_stalker_sakharov_squad") elseif stage == 5 then return elseif stage == 4 then return elseif stage == 3 then local smart = SIMBOARD.smarts_by_names["prom_1"] return smart and smart.id elseif stage == 2 then local smart = SIMBOARD.smarts_by_names["prom_1"] return smart and smart.id elseif stage == 1 then local restr = get_story_se_object("redemption_dummy_target") return restr and restr.id end end end task_status_functor.redemption_6_status_functor = function(tsk,task_id) if not tsk then return end if not tsk.stage then tsk.stage = 0 end -- duty start attack if HI("redemption_6_stage_2") and (not HI("redemption_6_stage_3")) then local duty_squad = get_story_se_object("redemption_task_6_duty_squad") if duty_squad and duty_squad.commander_id then for m in duty_squad:squad_members() do local duty_member = m.id and level.object_by_id(m.id) if duty_member and duty_member.alive and duty_member:alive() then local enemy = duty_member:best_enemy() if enemy and string.find(enemy:section(), "monolith") and (not HI("redemption_6_attack_time")) then GI("redemption_6_attack_time") GI("redemption_6_stage_3") DI("redemption_6_stage_2") -- make freedom companions -- local freedom_cap = get_story_object("redemption_task_6_freedom_captain") -- if freedom_cap and freedom_cap.alive and freedom_cap:alive() then -- dialogs_axr_companion.become_actor_companion(db.actor, freedom_cap) -- end end end end end end -- spawn more monolith if HI("redemption_6_stage_3") and (not HI("redemption_6_stage_4")) then -- news when we reach smart local smart = SIMBOARD.smarts_by_names["prom_1"] if (not HI("redemption_6_reach_smart_prom_1")) and smart and db.actor:position():distance_to(smart.position) < 25 then GI("redemption_6_reach_smart_prom_1") local se_squad = get_story_se_object("redemption_task_6_freedom_squad") if se_squad and se_squad.commander_id then local sender for m in se_squad:squad_members() do sender = m.id and level.object_by_id(m.id) end if sender and sender.alive and sender:alive() then redemption_pda_news("st_redemption_6_freedom_news", true, sender, 1, 12, "beep_1") -- remove freedom companions -- dialogs_axr_companion.remove_companions_from_squad(db.actor, sender) end end end -- when we inside spawn backup squads to attack and one inside if (not HI("redemption_6_mono_inside")) then local start_pos = vector():set(72.8, -43.0217, 304.5) if start_pos and db.actor:position():distance_to(start_pos) < 10 then redemption_spawn_squad_on_smart("prom_6", "redemption_task_5_monolith_squad_backup_1") redemption_spawn_squad_on_smart("prom_10", "redemption_task_5_monolith_squad_backup_2") redemption_spawn_squad_on_smart("prom_15", "redemption_task_5_monolith_squad_backup_3") GI("redemption_6_mono_inside") local se_inside_squad = redemption_spawn_squad_on_smart("prom_1", "redemption_task_5_monolith_inside") if se_inside_squad then redemption_set_squad_position(se_inside_squad, 408329) end end end -- new stage on entering bunker if level.name() == "bunker_a1" then GI("redemption_6_stage_4") DI("redemption_6_stage_3") redemption_open_route("bunk", "col") end end -- new stage on entering collider if HI("redemption_6_stage_4") and (not HI("redemption_6_stage_5")) and level.name() == "collaider" then redemption_unlock_collider_route() GI("redemption_6_stage_5") DI("redemption_6_stage_4") end -- collider if HI("redemption_6_stage_5") and (not HI("redemption_6_stage_6")) then -- spawn monolith if HI("redemption_6_switcher_1_pressed") and HI("redemption_6_switcher_2_pressed") and (not HI("redemption_6_switcher_mono_spawn")) then GI("redemption_6_switcher_mono_spawn") redemption_6_spawn_vakhar_squad() end -- collider reseted if HI("redemption_6_switcher_3_pressed") then GI("redemption_6_stage_6") DI("redemption_6_stage_5") redemption_6_release_mono_outside() redemption_6_spawn_dead_monolith() end end -- vakhar disable looting if HI("redemption_6_stage_5") or HI("redemption_6_stage_6") then local vakhar_squad = get_story_se_object("redemption_task_6_monolith_vakhar_squad") if vakhar_squad and vakhar_squad.commander_id then for m in vakhar_squad:squad_members() do local member = m.id and level.object_by_id(m.id) if member and member.alive and member:alive() and db.storage[member:id()] and db.storage[member:id()].corpse_detection then db.storage[member:id()].corpse_detection.selected_corpse_id = nil end end end end -- actor goes up after collider if HI("redemption_6_stage_6") and level.name() == "promzona" and (not HI("redemption_6_duty_freedom_scene")) then local smart = SIMBOARD.smarts_by_names["prom_1"] local dist = smart and db.actor:position():distance_to(smart.position) if dist and dist < 51 then GI("redemption_6_duty_freedom_scene") local duty_squad = get_story_se_object("redemption_task_6_duty_squad") if duty_squad then redemption_set_squad_position(duty_squad, 404786) end local freed_squad = get_story_se_object("redemption_task_6_freedom_squad") if freed_squad then redemption_set_squad_position(freed_squad, 391293) end end end -- duty or freedom tells if HI("redemption_6_stage_6") and level.name() == "promzona" and (not HI("redemption_6_duty_freedom_news")) then local smart = SIMBOARD.smarts_by_names["prom_1"] local dist = smart and db.actor:position():distance_to(smart.position) if dist and dist < 30 then GI("redemption_6_duty_freedom_news") local sender local freed_squad = get_story_se_object("redemption_task_6_freedom_squad") if freed_squad and freed_squad.commander_id then for m in freed_squad:squad_members() do sender = sender or m.id and level.object_by_id(m.id) end end local duty_squad = get_story_se_object("redemption_task_6_duty_squad") if duty_squad and duty_squad.commander_id then for m in duty_squad:squad_members() do sender = sender or m.id and level.object_by_id(m.id) end end if sender and sender.alive and sender:alive() then redemption_pda_news("st_redemption_6_duty_freedom_news", true, sender, 1, 12, "beep_1") end end end if HI("redemption_6_stage_6") then tsk.stage = 6 -- return to sakharov return elseif HI("redemption_6_stage_5") then tsk.stage = 5 -- reset collider return elseif HI("redemption_6_stage_4") then tsk.stage = 4 -- enter collider return elseif HI("redemption_6_stage_3") then tsk.stage = 3 -- enter bunker return elseif HI("redemption_6_stage_2") then tsk.stage = 2 -- wait for duty attack return elseif HI("redemption_6_stage_1") then tsk.stage = 1 -- go to promzone return end end function redemption_6_respawn_monolith() for i = 1, 4 do redemption_release_squad("redemption_task_5_monolith_squad_" .. i) end CreateTimeEvent("redemption_6_spawn_mono_e", "redemption_6_spawn_mono_a", 2, function() for i = 1, 4 do redemption_spawn_squad_on_smart("prom_1", "redemption_task_5_monolith_squad_" .. i) end return true end) end function redemption_6_spawn_target() alife_create("redemption_dummy_target", vector():set(-153.3, -27.6538, 184.8), 166300, 5370) end function redemption_6_release_target() local restr = get_story_se_object("redemption_dummy_target") if restr then alife_release(restr) end end function redemption_6_release_prom_sim_squads() redemption_release_sim_squads_on_smart("prom_5") redemption_release_sim_squads_on_smart("prom_6") redemption_release_sim_squads_on_smart("prom_10") redemption_release_sim_squads_on_smart("prom_15") end function redemption_6_spawn_freedom_squad() redemption_spawn_squad_on_smart("prom_6", "redemption_task_6_freedom_squad") if HI("redemption_task_4_bloodsuckers_killed") then CreateTimeEvent("redemption_6_add_stalker_e", "redemption_6_add_stalker_a", 1, function() local squad = get_story_se_object("redemption_task_6_freedom_squad") local smart = SIMBOARD.smarts_by_names["prom_6"] if squad and squad.commander_id and smart then local id = squad:add_squad_member("redemption_task_6_stalker", smart.position, smart.m_level_vertex_id, smart.m_game_vertex_id) local se_stalker = id and alife_object(id) if (se_stalker) then smart:register_npc(se_stalker) SIMBOARD:setup_squad_and_group(se_stalker) end squad:update() end return true end) end end function redemption_6_spawn_prom_block() alife_create("redemption_6_block_1", vector():set(39.7, -29.0007, 296.5), 395129, 5360) alife_create("redemption_6_block_2", vector():set(40.7, -29.0007, 296.5), 395129, 5360) alife_create("redemption_6_block_3", vector():set(39.0, -29.0007, 296.2), 395129, 5360) alife_create("redemption_6_block_4", vector():set(40.0, -29.0007, 296.2), 395129, 5360) end function redemption_6_spawn_duty_squad() redemption_spawn_squad_on_smart("prom_15", "redemption_task_6_duty_squad") end function redemption_6_duty_freedom_enemy_eval(obj, enemy, flags) if not (HI("redemption_6_final")) then return end local obj_comm = IsStalker(obj) and obj:character_community() local en_comm = IsStalker(enemy) and enemy:character_community() if not (obj_comm and en_comm) then return end local duty_freed = obj_comm == "dolg" and en_comm == "freedom" local freed_duty = obj_comm == "freedom" and en_comm == "dolg" if duty_freed or freed_duty then flags.override = true flags.result = false end end function redemption_6_release_mono_outside() for i = 1, 4 do redemption_release_squad("redemption_task_5_monolith_squad_" .. i) end for i = 1, 3 do redemption_release_squad("redemption_task_5_monolith_squad_backup_" .. i) end redemption_release_squad("redemption_task_5_monolith_inside") end function redemption_6_spawn_dead_monolith() -- insane 1, 2 alife_create("redemption_task_6_mono_insane_1", vector():set(36.4, -27.6538, 266), 391282, 5360) alife_create("redemption_task_6_mono_insane_2", vector():set(2.8, -27.6538, 215.6), 346518, 5362) -- dead local dead1 = alife_create("redemption_task_6_mono_dead_1", vector():set(44.8, -27.6538, 232.4), 402190, 5361) if dead1 then dead1:kill() end local dead2 = alife_create("redemption_task_6_mono_dead_2", vector():set(34.3, -27.6538, 240.8), 388443, 5361) if dead2 then dead2:kill() end local dead3 = alife_create("sim_default_monolith_4", vector():set(46.2, -27.6538, 213.5), 403885, 5361) if dead3 then dead3:kill() end local dead4 = alife_create("sim_default_monolith_2", vector():set(24.5, -26.5518, 203), 375130, 5361) if dead4 then dead4:kill() end local dead5 = alife_create("sim_default_monolith_3", vector():set(37.1, -27.6538, 280.7), 392264, 5360) if dead5 then dead5:kill() end local dead6 = alife_create("sim_default_monolith_2", vector():set(59.5, -27.6538, 202.3), 420070, 5361) if dead6 then dead6:kill() end local dead7 = alife_create("sim_default_monolith_1", vector():set(-11.2, -26.5518, 203), 326562, 5362) if dead7 then dead7:kill() end end function redemption_6_spawn_vakhar_squad() redemption_spawn_squad_on_smart("collaider_4", "redemption_task_6_monolith_vakhar_squad") CreateTimeEvent("redemption_6_vakhar_news_e", "redemption_6_vakhar_news_a", 1, function() local se_obj = get_story_se_object("redemption_task_6_monolith_vakhar") if se_obj then redemption_pda_news("st_redemption_6_vakhar_1", true, se_obj, 3, 14) if HI("redemption_5_illeon_is_companion") and (not HI("redemption_task_5_illeon_death")) then redemption_pda_news("st_redemption_6_vakhar_2", true, se_obj, 9, 14) end end return true end) end function redemption_6_ignore_insane_mono(obj, enemy, flags) if not HI("redemption_6_stage_6") then return end local mono1 = get_story_object("redemption_task_6_mono_insane_1") local mono1_cond = mono1 and mono1.alive and mono1:alive() and mono1:id() == enemy:id() local mono2 = get_story_object("redemption_task_6_mono_insane_2") local mono2_cond = mono2 and mono2.alive and mono2:alive() and mono2:id() == enemy:id() if mono1_cond or mono2_cond then flags.override = true flags.result = false end end function redemption_6_finish_release_everything() -- blocking for i = 1, 4 do local se_obj = get_story_se_item("redemption_6_block_" .. i) if se_obj then alife_release(se_obj) end end -- dead monolith redemption_release_npc("redemption_task_6_mono_insane_1") redemption_release_npc("redemption_task_6_mono_insane_2") redemption_release_npc("redemption_task_6_mono_dead_1") redemption_release_npc("redemption_task_6_mono_dead_2") -- vakhar freedom duty redemption_release_squad("redemption_task_6_monolith_vakhar") redemption_release_squad("redemption_task_6_freedom_squad") redemption_release_squad("redemption_task_6_duty_squad") end function redemption_6_give_reward(a, b) local num = 60000 dialogs.relocate_money_to_actor(a, b, num) end function redemption_6_give_goodwill() redemption_goodwill_gain("ecolog", 500) redemption_goodwill_gain("freedom", 350) redemption_goodwill_gain("dolg", 350) redemption_goodwill_gain("stalker", 200) end function end_redemption_task_6() task_manager.get_task_manager():set_task_completed("redemption_task_6") end -- ///////////////////////// Post redemption ///////////////////////// function redemption_end_spawn_lab_items() local lab_items_ar = { { pos = {161.11, 3.59, 22.48}, angle = 3.14 }, { pos = {133.18, 6.22, -65.55}, angle = 0.75 }, { pos = {-1, 8.14, -22.6}, angle = 0 }, { pos = {24.75, -2.17, -7.23}, angle = 1.57 }, { pos = {-17.8, -0.62, 25.76}, angle = 0 }, { pos = {-28.04, -0.85, 31.64}, angle = 0 }, { pos = {23.48, 2.59, 51.1}, angle = 0 }, { pos = {-5.7, 4.57, 40.1}, angle = 0 }, } for idx, t in ipairs(lab_items_ar) do local se_obj = alife_create("redemption_lab_item_" .. idx, vector():set(t.pos[1], t.pos[2], t.pos[3]), 4294967295, 6113) if se_obj then se_obj.angle = vector():set(0, t.angle, 0) end end end function redemption_voronin_reward_precond() if (HI("redemption_6_stage_6") or HI("redemption_storyline_finished")) and (not HI("redemption_end_voronin_reward")) then return true end end function redemption_voronin_give_reward(a, b) dialogs.relocate_item_section_to_actor(a, b, "wpn_vepr_kobra") end function redemption_lukash_reward_precond() if (HI("redemption_6_stage_6") or HI("redemption_storyline_finished")) and (not HI("redemption_end_lukash_reward")) then return true end end function redemption_lukash_give_reward(a, b) dialogs.relocate_item_section_to_actor(a, b, "freedom_exo_vineleaf_outfit") end function redemption_actor_has_lab_items() if not HI("redemption_storyline_finished") then return end for i = 1, 8 do if db.actor:object("redemption_lab_item_" .. i) then return true end end end function redemption_lab_items_reward(a, b) local money_per_item = 2500 local itms_given = 0 local gw_per_item = 25 for i = 1, 8 do if db.actor:object("redemption_lab_item_" .. i) then dialogs.relocate_item_section_from_actor(a, b, "redemption_lab_item_" .. i) itms_given = itms_given + 1 redemption_end_items_found = redemption_end_items_found + 1 end end if itms_given > 0 then dialogs.relocate_money_to_actor(a, b, itms_given * money_per_item) redemption_goodwill_gain("ecolog", itms_given * gw_per_item) end end function redemption_all_lab_items_collected() if redemption_end_items_found >= 8 then return true end end function redemption_not_all_lab_items_collected() if redemption_end_items_found < 8 then return true end end function redemption_all_lab_items_reward(a, b) dialogs.relocate_item_section_to_actor(a, b, "af_plates_up") dialogs.relocate_item_section_to_actor(a, b, "af_freon_up") dialogs.relocate_item_section_to_actor(a, b, "ration_ru") dialogs.relocate_item_section_to_actor(a, b, "medkit_ai3") dialogs.relocate_item_section_to_actor(a, b, "drug_radioprotector") dialogs.relocate_item_section_to_actor(a, b, "akvatab") redemption_goodwill_gain("ecolog", 100) end -- ////////////////////////////////////////////////// function save_state(m_data) m_data.redemption_3_start_time = redemption_3_start_time m_data.redemption_4_start_time = redemption_4_start_time m_data.redemption_4_aggro_time = redemption_4_aggro_time m_data.redemption_5_start_time = redemption_5_start_time m_data.redemption_end_items_found = redemption_end_items_found end function load_state(m_data) redemption_3_start_time = m_data.redemption_3_start_time or nil redemption_4_start_time = m_data.redemption_4_start_time or nil redemption_4_aggro_time = m_data.redemption_4_aggro_time or nil redemption_5_start_time = m_data.redemption_5_start_time or nil redemption_end_items_found = m_data.redemption_end_items_found or 0 end function redemption_cancel_transition() local cancel_tp = false local ini = ini_file("sr_teleport_sections.ltx") if debug_unlock_labs then return end if not (HI("redemption_6_unlock_collider_route")) then local to_col = get_story_se_object("prom_space_restrictor_to_collider") local to_col_dist = to_col and to_col.online and db.actor:position():distance_to(to_col.position) if to_col_dist and to_col_dist < 20 then local path = ini:r_string_ex("prom_space_restrictor_to_collider", "reject_path") local point = path and patrol(path) db.actor:set_actor_position(point and point:point(0) or db.actor:position()) cancel_tp = true end end if not (HI("redemption_6_unlock_bunker_route")) then local to_bunk = get_story_se_object("prom_space_restrictor_to_bunker") local to_bunk_dist = to_bunk and to_bunk.online and db.actor:position():distance_to(to_bunk.position) if to_bunk_dist and to_bunk_dist < 20 then local path = ini:r_string_ex("prom_space_restrictor_to_bunker", "reject_path") local point = path and patrol(path) db.actor:set_actor_position(point and point:point(0) or db.actor:position()) cancel_tp = true end end if cancel_tp then level.remove_pp_effector(1313) actor_menu.set_msg(1, game.translate_string("st_route_unknown"), 7) CreateTimeEvent("redemption_cancel_time_event_e", "redemption_cancel_time_event_a", 1, function() RemoveTimeEvent(0, "delay_travel") return true end) end end function on_game_start() RegisterScriptCallback("on_enemy_eval", redemption_2_bandit_enemy_eval) RegisterScriptCallback("npc_on_before_hit", redemption_2_bandit_before_hit) RegisterScriptCallback("save_state", save_state) RegisterScriptCallback("load_state", load_state) RegisterScriptCallback("actor_on_before_hit", redemption_3_actor_before_hit) RegisterScriptCallback("actor_on_update", redemption_3_health_update) RegisterScriptCallback("on_enemy_eval", redemption_4_bandits_enemy_eval) RegisterScriptCallback("npc_on_before_hit", redemption_4_bandits_before_hit) RegisterScriptCallback("on_enemy_eval", redemption_5_ignore_dutier) RegisterScriptCallback("on_enemy_eval", redemption_5_duty_freedom_enemy_eval) RegisterScriptCallback("on_enemy_eval", redemption_6_duty_freedom_enemy_eval) RegisterScriptCallback("on_before_level_changing", redemption_cancel_transition) RegisterScriptCallback("on_enemy_eval", redemption_6_ignore_insane_mono) end