Divergent/mods/New Levels/gamedata/scripts/dialogs_redemption_storylin...

2086 lines
67 KiB
Plaintext

-- ///////////////////////// 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