1485 lines
76 KiB
Plaintext
1485 lines
76 KiB
Plaintext
|
---==================================================================================================================---
|
||
|
--- ---
|
||
|
--- Original Author(s) : NLTP_ASHES ---
|
||
|
--- Edited : N/A ---
|
||
|
--- Date : 17/04/2023 ---
|
||
|
--- License : Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) ---
|
||
|
--- ---
|
||
|
--- Script used to manage the tasks of the first act of the addon's storyline. ---
|
||
|
--- ---
|
||
|
--- Each task is composed of the following elements : ---
|
||
|
--- - A act_1_task_X_start(...) function, used to start the task; ---
|
||
|
--- - A act_1_task_X_end(...) function, used to end the task; ---
|
||
|
--- - A xr_effects.act_1_task_X_init(...) function, called when the task has started; ---
|
||
|
--- - A xr_effects.act_1_task_X_complete(...) function, called when the task was successfully completed; ---
|
||
|
--- - A xr_effects.act_1_task_X_fail(...) function, called when the task was failed; ---
|
||
|
--- - A task_functor.act_1_task_X_title_f(...) function, called periodically to get the name; ---
|
||
|
--- - A task_functor.act_1_task_X_descr_f(...) function, called periodically to get the description; ---
|
||
|
--- - A task_functor.act_1_task_X_target_f(...) function, called periodically to get the target (for the PDA); ---
|
||
|
--- - A task_status_functor.act_1_task_X_status_f(...) function, called periodically to run the core logic. ---
|
||
|
--- ---
|
||
|
---==================================================================================================================---
|
||
|
|
||
|
-- ---------------------------------------------------------------------------------------------------------------------
|
||
|
-- Constants, global variables and imported functions
|
||
|
-- ---------------------------------------------------------------------------------------------------------------------
|
||
|
|
||
|
-- Imported functions
|
||
|
local dbg_printf = western_goods_utils.dbg_printf
|
||
|
local level_object_by_id = western_goods_utils.level_object_by_id
|
||
|
local spawn_squad = western_goods_utils.spawn_squad
|
||
|
local spawn_dead_squad = western_goods_utils.spawn_dead_squad
|
||
|
local spawn_story_squad = western_goods_utils.spawn_story_squad
|
||
|
local send_dialog = western_goods_dialogs_manager.send_dialog
|
||
|
local heli_spawn = western_goods_helicopter.heli_spawn
|
||
|
local heli_register = western_goods_helicopter.heli_register
|
||
|
local HELICOPTERS_MODES = western_goods_helicopter.HELICOPTERS_MODES
|
||
|
|
||
|
-- Constants
|
||
|
local CONST_TASK_2_HARD_DELAY = 1800000 -- milliseconds
|
||
|
local CONST_TASK_3_HARD_DELAY = 1800000 -- milliseconds
|
||
|
local CONST_TASK_1_HELI_DIST = 625 -- meters squared
|
||
|
local CONST_TASK_1_SUPPLIES_DIST = 25 -- meters squared
|
||
|
local CONST_TASK_1_PROGRESS_DELAY = 43000 -- milliseconds
|
||
|
local CONST_TASK_2_HELI_DELAY = 50000 -- milliseconds
|
||
|
local CONST_TASK_2_SHOW_TARGETS_DELAY = 300000 -- milliseconds
|
||
|
local CONST_TASK_2_REP_THEFT = -100 -- reputation points
|
||
|
local CONST_TASK_3_PROGRESS_DELAY = 38000 -- milliseconds
|
||
|
local CONST_TASK_3_SHOW_TARGETS_DELAY = 300000 -- milliseconds
|
||
|
local CONST_TASK_3_DIALOG_DIST = 625 -- meters squared
|
||
|
local CONST_TASK_3_DIALOG_EX_DIST = 2500 -- meters squared
|
||
|
local CONST_TASK_3_BRIDGE_DIST = 10000 -- meters squared
|
||
|
local CONST_TASK_3_HELI_DIST = 100 -- meters squared
|
||
|
local CONST_TASK_3_NPC_DIST = 25 -- meters squared
|
||
|
|
||
|
-- Task variables
|
||
|
TASK_1_CACHE = {}
|
||
|
TASK_2_CACHE = {}
|
||
|
TASK_3_CACHE = {}
|
||
|
|
||
|
-- ---------------------------------------------------------------------------------------------------------------------
|
||
|
-- ACT 1 - HELICOPTER DELIVERY
|
||
|
-- ---------------------------------------------------------------------------------------------------------------------
|
||
|
-- TASK 1 - ROAD BUMPS
|
||
|
-- ---------------------------------------------------------------------------------------------------------------------
|
||
|
|
||
|
--- Function used to start Act 1, Task 1.
|
||
|
--- @param first_speaker cse_alife_object
|
||
|
--- @param second_speaker cse_alife_object
|
||
|
--- @return nil
|
||
|
function act_1_task_1_start(first_speaker, second_speaker)
|
||
|
local npc = dialogs.who_is_npc(first_speaker, second_speaker)
|
||
|
task_manager.get_task_manager():give_task("western_goods_act_1_task_1", npc:id())
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 1 - Task started...")
|
||
|
end
|
||
|
|
||
|
--- Function used to end Act 1, Task 1.
|
||
|
--- @return nil
|
||
|
function act_1_task_1_end()
|
||
|
task_manager.get_task_manager():set_task_completed("western_goods_act_1_task_1")
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 1 - Task completed...")
|
||
|
end
|
||
|
|
||
|
--- Function called when the task is initiated.
|
||
|
--- @param actor cse_alife_object
|
||
|
--- @param npc cse_alife_object
|
||
|
--- @return nil
|
||
|
function xr_effects.act_1_task_1_init(actor,npc)
|
||
|
-- Process info portions
|
||
|
western_goods_utils.give_info("western_goods_act_1_task_1_active")
|
||
|
western_goods_utils.give_info("western_goods_act_1_task_1_init")
|
||
|
end
|
||
|
|
||
|
--- Function called when the task is successfully completed.
|
||
|
--- @param actor cse_alife_object
|
||
|
--- @param npc cse_alife_object
|
||
|
--- @return nil
|
||
|
function xr_effects.act_1_task_1_complete(actor,npc)
|
||
|
-- Process info portions
|
||
|
western_goods_utils.rem_info("western_goods_act_1_task_1_active")
|
||
|
western_goods_utils.give_info("western_goods_act_1_task_1_finished")
|
||
|
western_goods_utils.rem_info("western_goods_act_1_task_1_init")
|
||
|
|
||
|
-- Process quest items
|
||
|
xr_effects.remove_item(actor, npc, {"wg_act_1_task_1_quest_item"})
|
||
|
|
||
|
-- Set up task 2
|
||
|
TASK_2_CACHE.available_time = time_global() + CONST_TASK_2_HARD_DELAY
|
||
|
|
||
|
-- Process reward
|
||
|
xr_effects.reward_random_money(actor,npc,{"5000","10000"})
|
||
|
xr_effects.reward_stash(actor,npc,{"true"})
|
||
|
xr_effects.complete_task_inc_goodwill(actor,npc,{"75","killer"})
|
||
|
end
|
||
|
|
||
|
--- Function called when the task is failed.
|
||
|
--- @param actor cse_alife_object
|
||
|
--- @param npc cse_alife_object
|
||
|
--- @return nil
|
||
|
function xr_effects.act_1_task_1_fail(actor,npc)
|
||
|
-- Process info portions
|
||
|
western_goods_utils.rem_info("western_goods_act_1_task_1_active")
|
||
|
western_goods_utils.rem_info("western_goods_act_1_task_1_init")
|
||
|
|
||
|
-- Process penalty
|
||
|
xr_effects.fail_task_dec_goodwill(actor,npc,{"75","killer"})
|
||
|
end
|
||
|
|
||
|
--- Function used to retrieve the title of the mission (displayed in the PDA).
|
||
|
--- @param task_id number
|
||
|
--- @param field string
|
||
|
--- @param p any
|
||
|
--- @param tsk CGameTask
|
||
|
--- @return string
|
||
|
function task_functor.act_1_task_1_title_f(task_id,field,p,tsk)
|
||
|
if true then
|
||
|
return western_goods_utils.get_translation("st_wg_act_1_task_1_title")
|
||
|
end
|
||
|
end
|
||
|
|
||
|
--- Function used to retrieve the description of the mission (displayed in the PDA).
|
||
|
--- Warning : naming contract on the translation string : st_wg_trader_act_1_task_1_stage_<stage>_descr.
|
||
|
--- @param task_id number
|
||
|
--- @param field string
|
||
|
--- @param p any
|
||
|
--- @param tsk CGameTask
|
||
|
--- @return string
|
||
|
function task_functor.act_1_task_1_descr_f(task_id,field,p,tsk)
|
||
|
if true then
|
||
|
return western_goods_utils.get_translation("st_wg_act_1_task_1_stage_" .. tostring(tsk.stage) .. "_descr")
|
||
|
end
|
||
|
end
|
||
|
|
||
|
--- Function used to retrieve the target of the mission (marker displayed (or not) in the PDA).
|
||
|
--- @param task_id number
|
||
|
--- @param field string
|
||
|
--- @param p any
|
||
|
--- @param tsk CGameTask
|
||
|
--- @return number
|
||
|
function task_functor.act_1_task_1_target_f(task_id,field,p,tsk)
|
||
|
if western_goods_utils.has_info("western_goods_act_1_task_1_init") then
|
||
|
if tsk.stage == 0 then
|
||
|
local heli_se = western_goods_utils.server_object_by_sid("western_goods_helicopter_landed")
|
||
|
return heli_se and heli_se.id
|
||
|
end
|
||
|
|
||
|
if tsk.stage == 1 then
|
||
|
local quest_item_se = western_goods_utils.server_object_by_sid("wg_act_1_task_1_quest_item")
|
||
|
return quest_item_se and quest_item_se.parent_id == 65535 and quest_item_se.id
|
||
|
end
|
||
|
|
||
|
if tsk.stage == 2 then
|
||
|
local quest_item_se = western_goods_utils.server_object_by_sid("wg_act_1_task_1_quest_item")
|
||
|
return quest_item_se and quest_item_se.parent_id == 65535 and quest_item_se.id
|
||
|
end
|
||
|
|
||
|
if tsk.stage == 3 then
|
||
|
return tsk.task_giver_id
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
--- Function used to manage the mission logic as a whole.
|
||
|
--- @param tsk CGameTask
|
||
|
--- @param task_id number
|
||
|
--- @return string
|
||
|
function task_status_functor.act_1_task_1_status_f(tsk,task_id)
|
||
|
if western_goods_utils.has_info("western_goods_act_1_task_1_init") then
|
||
|
-- First stage : Get to the helicopter
|
||
|
if tsk.stage == 0 then
|
||
|
-- Retrieve the server and game objects (they may not always exist - if they aren't spawned yet or unavailable)
|
||
|
local helicopter_se = western_goods_utils.server_object_by_sid("western_goods_helicopter_landed")
|
||
|
local helicopter_obj = western_goods_utils.level_object_by_sid("western_goods_helicopter_landed")
|
||
|
|
||
|
-- If the heli hasn't been created, then create it
|
||
|
if not helicopter_se then
|
||
|
create_story_helicopter("zaton")
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- Continue if the player is closer than 25m from the helicopter
|
||
|
if not helicopter_obj or western_goods_utils.get_distance_sqr(helicopter_obj:position(), db.actor:position()) > CONST_TASK_1_HELI_DIST then return end
|
||
|
|
||
|
-- Send a dialog between the task giver and the player
|
||
|
if not TASK_1_CACHE.stage_0_dialog_sent then
|
||
|
local sender_1 = alife():actor()
|
||
|
local sender_2 = tsk.task_giver_id and alife_object(tsk.task_giver_id)
|
||
|
|
||
|
local dialog_sender_1 = { name=sender_1:character_name(), icon=sender_1:character_icon()}
|
||
|
local dialog_sender_2 = { name=sender_2:character_name(), icon=sender_2:character_icon()}
|
||
|
|
||
|
send_dialog({
|
||
|
{sender=dialog_sender_2.name, icon=dialog_sender_2.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_1_stage_0_message_1")},
|
||
|
{sender=dialog_sender_1.name, icon=dialog_sender_1.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_1_stage_0_message_2")},
|
||
|
{sender=dialog_sender_2.name, icon=dialog_sender_2.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_1_stage_0_message_3")},
|
||
|
{sender=dialog_sender_1.name, icon=dialog_sender_1.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_1_stage_0_message_4")},
|
||
|
{sender=dialog_sender_2.name, icon=dialog_sender_2.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_1_stage_0_message_5")},
|
||
|
{sender=dialog_sender_2.name, icon=dialog_sender_2.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_1_stage_0_message_6")}
|
||
|
})
|
||
|
|
||
|
TASK_1_CACHE.progress_timer = time_global() + CONST_TASK_1_PROGRESS_DELAY
|
||
|
TASK_1_CACHE.stage_0_dialog_sent = true
|
||
|
end
|
||
|
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 1 - Stage 0 - Player arrived at helicopter...")
|
||
|
|
||
|
-- Progress the task
|
||
|
if TASK_1_CACHE.progress_timer < time_global() then
|
||
|
tsk.stage = 1
|
||
|
return
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Second stage : Get to the crew at the sawmill and recover the supplies
|
||
|
if tsk.stage == 1 then
|
||
|
-- Retrieve the server and game objects (they may not always exist - if they aren't spawned yet or unavailable)
|
||
|
local supplies_se = western_goods_utils.server_object_by_sid("wg_act_1_task_1_quest_item")
|
||
|
local supplies_obj = western_goods_utils.level_object_by_sid("wg_act_1_task_1_quest_item")
|
||
|
|
||
|
-- Spawn the crew of the helicopter dead at the sawmill
|
||
|
if not TASK_1_CACHE.stage_1_npcs_spawned then
|
||
|
-- Spawn the merc squad, dead, at the sawmill
|
||
|
spawn_dead_squad("western_goods_act_1_task_1_heli_crew_squad", "zat_b104_zombied")
|
||
|
|
||
|
-- Spawn the zombies that supposedly killed them
|
||
|
spawn_dead_squad("western_goods_act_1_task_1_zombie_1_squad", "zat_b104_zombied")
|
||
|
spawn_dead_squad("western_goods_act_1_task_1_zombie_2_squad", "zat_b104_zombied")
|
||
|
spawn_dead_squad("western_goods_act_1_task_1_zombie_3_squad", "zat_b104_zombied")
|
||
|
spawn_dead_squad("western_goods_act_1_task_1_zombie_4_squad", "zat_b104_zombied")
|
||
|
|
||
|
-- Give an info portion so the spawning code doesn't run twice
|
||
|
TASK_1_CACHE.stage_1_npcs_spawned = true
|
||
|
|
||
|
-- Return so the squad has time to spawn in the game world
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- Spawn the supplies if they don't exist in the world
|
||
|
if not supplies_se then
|
||
|
-- Spawn the supplies, objective the player has to retrieve
|
||
|
supplies_se = alife_create("wg_act_1_task_1_quest_item", vector():set(-317.4,9.8,425.5), 327181, 4137)
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 1 - Stage 1 - Quest item spawned %s", supplies_se.id)
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- Wait for the player to be close to the supplies
|
||
|
if not supplies_obj or western_goods_utils.get_distance_sqr(supplies_obj:position(), db.actor:position()) > CONST_TASK_1_SUPPLIES_DIST then return end
|
||
|
|
||
|
-- Send a dialog between the task giver and the player
|
||
|
if not TASK_1_CACHE.stage_1_dialog_sent then
|
||
|
local sender_1 = alife():actor()
|
||
|
local sender_2 = tsk.task_giver_id and alife_object(tsk.task_giver_id)
|
||
|
|
||
|
local dialog_sender_1 = { name=sender_1:character_name(), icon=sender_1:character_icon()}
|
||
|
local dialog_sender_2 = { name=sender_2:character_name(), icon=sender_2:character_icon()}
|
||
|
|
||
|
send_dialog({
|
||
|
{sender=dialog_sender_1.name, icon=dialog_sender_1.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_1_stage_1_message_1")},
|
||
|
{sender=dialog_sender_2.name, icon=dialog_sender_2.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_1_stage_1_message_2")},
|
||
|
{sender=dialog_sender_1.name, icon=dialog_sender_1.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_1_stage_1_message_3")},
|
||
|
{sender=dialog_sender_2.name, icon=dialog_sender_2.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_1_stage_1_message_4")}
|
||
|
})
|
||
|
|
||
|
TASK_1_CACHE.stage_1_dialog_sent = true
|
||
|
end
|
||
|
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 1 - Stage 1 - Player arrived at the dead squad...")
|
||
|
|
||
|
-- Progress the task
|
||
|
tsk.stage = 2
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- Third stage : Take the supplies and bring them back to the trader
|
||
|
if tsk.stage == 2 then
|
||
|
-- Retrieve the server object (they may not exist - if they have been picked up by the player)
|
||
|
local supplies_se = western_goods_utils.server_object_by_sid("wg_act_1_task_1_quest_item")
|
||
|
|
||
|
-- If the supplies cannot be found (which is odd), roll back to stage 1
|
||
|
if not supplies_se then
|
||
|
-- Spawn the supplies, objective the player has to retrieve
|
||
|
supplies_se = alife_create("wg_act_1_task_1_quest_item", vector():set(-317.4,9.8,425.5), 327181, 4137)
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 1 - Stage 2 - Quest item respawned %s", supplies_se.id)
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- If the player picked up the supplies, progress to stage 3
|
||
|
if not (supplies_se and (supplies_se.parent_id ~= AC_ID)) then
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 1 - Stage 2 - Player picked up the supplies %s", supplies_se.id)
|
||
|
tsk.stage = 3
|
||
|
return
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Fourth stage : Bringing the supplies to the trader. If the supplies are dropped, rollback to the previous stage
|
||
|
if tsk.stage == 3 then
|
||
|
-- Retrieve the server object (they may exist - if they have been dropped by the player)
|
||
|
local supplies_se = western_goods_utils.server_object_by_sid("wg_act_1_task_1_quest_item")
|
||
|
|
||
|
-- If the supplies cannot be found (which is odd), roll back to stage 2
|
||
|
if not supplies_se then
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 1 - Stage 3 - Supplies disappeared, rolling back to stage 2...")
|
||
|
tsk.stage = 2
|
||
|
return
|
||
|
end
|
||
|
|
||
|
if not western_goods_utils.has_info("western_goods_act_1_task_1_ready_finished") then
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 1 - Task ready to be completed...")
|
||
|
western_goods_utils.give_info("western_goods_act_1_task_1_ready_finished")
|
||
|
end
|
||
|
|
||
|
-- If the player dropped the supplies, rollback to stage 2
|
||
|
if supplies_se and (supplies_se.parent_id ~= AC_ID) then
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 1 - Stage 3 - Player dropped the supplies %s", supplies_se.id)
|
||
|
|
||
|
if western_goods_utils.has_info("western_goods_act_1_task_1_ready_finished") then
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 1 - Task no longer ready to be completed...")
|
||
|
western_goods_utils.rem_info("western_goods_act_1_task_1_ready_finished")
|
||
|
end
|
||
|
|
||
|
tsk.stage = 2
|
||
|
return
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- ---------------------------------------------------------------------------------------------------------------------
|
||
|
-- TASK 2 - CONSPIRACY
|
||
|
-- ---------------------------------------------------------------------------------------------------------------------
|
||
|
|
||
|
--- Function used to start Act 1, Task 2.
|
||
|
--- @param first_speaker cse_alife_object
|
||
|
--- @param second_speaker cse_alife_object
|
||
|
--- @return nil
|
||
|
function act_1_task_2_start(first_speaker, second_speaker)
|
||
|
local npc = dialogs.who_is_npc(first_speaker, second_speaker)
|
||
|
task_manager.get_task_manager():give_task("western_goods_act_1_task_2", npc:id())
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 2 - Task started...")
|
||
|
end
|
||
|
|
||
|
--- Function used to end Act 1, Task 2.
|
||
|
--- @return nil
|
||
|
function act_1_task_2_end()
|
||
|
task_manager.get_task_manager():set_task_completed("western_goods_act_1_task_2")
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 2 - Task completed...")
|
||
|
end
|
||
|
|
||
|
--- Function called when the task is initiated.
|
||
|
--- @param actor cse_alife_object
|
||
|
--- @param npc cse_alife_object
|
||
|
--- @return nil
|
||
|
function xr_effects.act_1_task_2_init(actor,npc)
|
||
|
-- Process info portions
|
||
|
western_goods_utils.give_info("western_goods_act_1_task_2_active")
|
||
|
western_goods_utils.give_info("western_goods_act_1_task_2_init")
|
||
|
end
|
||
|
|
||
|
--- Function called when the task is successfully completed.
|
||
|
--- @param actor cse_alife_object
|
||
|
--- @param npc cse_alife_object
|
||
|
--- @return nil
|
||
|
function xr_effects.act_1_task_2_complete(actor,npc)
|
||
|
-- Process info portions
|
||
|
western_goods_utils.rem_info("western_goods_act_1_task_2_active")
|
||
|
western_goods_utils.rem_info("western_goods_act_1_task_2_init")
|
||
|
western_goods_utils.give_info("western_goods_act_1_task_2_finished")
|
||
|
|
||
|
-- Process quest items
|
||
|
xr_effects.remove_item(actor, npc, {"wg_act_1_task_2_quest_item_1"})
|
||
|
xr_effects.remove_item(actor, npc, {"wg_act_1_task_2_quest_item_2"})
|
||
|
|
||
|
-- Set up task 3
|
||
|
TASK_3_CACHE.available_time = time_global() + CONST_TASK_3_HARD_DELAY
|
||
|
|
||
|
-- Process reward
|
||
|
xr_effects.reward_random_money(actor,npc,{"10000","20000"})
|
||
|
xr_effects.complete_task_inc_goodwill(actor,npc,{"75","killer"})
|
||
|
end
|
||
|
|
||
|
--- Function called when the task is failed.
|
||
|
--- @param actor cse_alife_object
|
||
|
--- @param npc cse_alife_object
|
||
|
--- @return nil
|
||
|
function xr_effects.act_1_task_2_fail(actor,npc)
|
||
|
-- Process info portions
|
||
|
western_goods_utils.rem_info("western_goods_act_1_task_2_active")
|
||
|
western_goods_utils.rem_info("western_goods_act_1_task_2_init")
|
||
|
western_goods_utils.rem_info("western_goods_jupiter_informant_first_meet_over")
|
||
|
|
||
|
-- Process penalty
|
||
|
xr_effects.fail_task_dec_goodwill(actor,npc,{"50","killer"})
|
||
|
end
|
||
|
|
||
|
--- Function used to retrieve the title of the mission (displayed in the PDA).
|
||
|
--- @param task_id number
|
||
|
--- @param field string
|
||
|
--- @param p any
|
||
|
--- @param tsk CGameTask
|
||
|
--- @return string
|
||
|
function task_functor.act_1_task_2_title_f(task_id,field,p,tsk)
|
||
|
if true then -- Cond to force my IDE to fold this fucking function correctly
|
||
|
return western_goods_utils.get_translation("st_wg_act_1_task_2_title")
|
||
|
end
|
||
|
end
|
||
|
|
||
|
--- Function used to retrieve the description of the mission (displayed in the PDA).
|
||
|
--- Warning : naming contract on the translation string : st_wg_trader_act_1_task_2_stage_<stage>_descr.
|
||
|
--- @param task_id number
|
||
|
--- @param field string
|
||
|
--- @param p any
|
||
|
--- @param tsk CGameTask
|
||
|
--- @return string
|
||
|
function task_functor.act_1_task_2_descr_f(task_id,field,p,tsk)
|
||
|
if true then -- Cond to force my IDE to fold this fucking function correctly
|
||
|
return western_goods_utils.get_translation("st_wg_act_1_task_2_stage_" .. tostring(tsk.stage) .. "_descr")
|
||
|
end
|
||
|
end
|
||
|
|
||
|
--- Function used to retrieve the target of the mission (marker displayed (or not) in the PDA).
|
||
|
--- @param task_id number
|
||
|
--- @param field string
|
||
|
--- @param p any
|
||
|
--- @param tsk CGameTask
|
||
|
--- @return number
|
||
|
function task_functor.act_1_task_2_target_f(task_id,field,p,tsk)
|
||
|
if western_goods_utils.has_info("western_goods_act_1_task_2_init") then
|
||
|
if tsk.stage == 0 then
|
||
|
if western_goods_mcm.get_config("guided_tasks") then
|
||
|
local informant_se = western_goods_utils.server_object_by_sid("stalker_jupiter_informant_squad")
|
||
|
return informant_se and informant_se.id
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if tsk.stage == 1 then
|
||
|
if western_goods_mcm.get_config("guided_tasks") then
|
||
|
local quest_item_1 = western_goods_utils.server_object_by_sid("wg_act_1_task_2_quest_item_1")
|
||
|
local quest_item_2 = western_goods_utils.server_object_by_sid("wg_act_1_task_2_quest_item_2")
|
||
|
return (quest_item_1 and quest_item_1.parent_id == 65535 and quest_item_1.id) or (quest_item_2 and quest_item_2.parent_id == 65535 and quest_item_2.id)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if tsk.stage == 2 then
|
||
|
local timer = TASK_2_CACHE.stage_2_show_targets_timer
|
||
|
if timer and timer < time_global() then
|
||
|
local squad_1_se = western_goods_utils.server_object_by_sid("western_goods_act_1_task_2_bandit_4_squad")
|
||
|
local squad_2_se = western_goods_utils.server_object_by_sid("western_goods_act_1_task_2_bandit_5_squad")
|
||
|
local squad_3_se = western_goods_utils.server_object_by_sid("western_goods_act_1_task_2_bandit_6_squad")
|
||
|
return (squad_1_se and squad_1_se.id) or (squad_2_se and squad_2_se.id) or (squad_3_se and squad_3_se.id)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if tsk.stage == 3 then
|
||
|
local quest_item_1 = western_goods_utils.server_object_by_sid("wg_act_1_task_2_quest_item_1")
|
||
|
local quest_item_2 = western_goods_utils.server_object_by_sid("wg_act_1_task_2_quest_item_2")
|
||
|
return (quest_item_1 and quest_item_1.parent_id == 65535 and quest_item_1.id) or (quest_item_2 and quest_item_2.parent_id == 65535 and quest_item_2.id)
|
||
|
end
|
||
|
|
||
|
if tsk.stage == 4 then
|
||
|
return tsk.task_giver_id
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
--- Function used to manage the mission logic as a whole.
|
||
|
--- @param tsk CGameTask
|
||
|
--- @param task_id number
|
||
|
--- @return string
|
||
|
function task_status_functor.act_1_task_2_status_f(tsk,task_id)
|
||
|
if western_goods_utils.has_info("western_goods_act_1_task_2_init") then
|
||
|
-- First stage : Find and question the informant at Yanov Station
|
||
|
if tsk.stage == 0 then
|
||
|
-- Retrieve the server object (they may not always exist - if they aren't spawned yet or unavailable)
|
||
|
local informant_squad_se = western_goods_utils.server_object_by_sid("stalker_jupiter_informant_squad")
|
||
|
|
||
|
-- Delete the old helicopter from the lake in Zaton
|
||
|
if not TASK_2_CACHE.stage_0_zaton_heli_released then
|
||
|
release_story_helicopter()
|
||
|
TASK_2_CACHE.stage_0_zaton_heli_released = true
|
||
|
end
|
||
|
|
||
|
-- Spawn a new one at the Water Processing Station
|
||
|
if not TASK_2_CACHE.stage_0_wps_heli_created then
|
||
|
create_story_helicopter("wps")
|
||
|
TASK_2_CACHE.stage_0_wps_heli_created = true
|
||
|
end
|
||
|
|
||
|
-- Spawn the informant if it doesn't exist
|
||
|
if not informant_squad_se then
|
||
|
informant_squad_se = spawn_story_squad("stalker_jupiter_informant_squad", vector():set(-55,3.8,211), SIMBOARD.smarts_by_names["jup_a6"])
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- When the player is done talking with the informant
|
||
|
if not western_goods_utils.has_info("western_goods_jupiter_informant_first_meet_over") then return end
|
||
|
|
||
|
-- Send a dialog between the task giver and the player
|
||
|
if not TASK_2_CACHE.stage_0_dialog_sent then
|
||
|
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 2 - Stage 0 - Player met informant...")
|
||
|
|
||
|
local sender_1 = alife():actor()
|
||
|
local sender_2 = tsk.task_giver_id and alife_object(tsk.task_giver_id)
|
||
|
|
||
|
local dialog_sender_1 = { name=sender_1:character_name(), icon=sender_1:character_icon()}
|
||
|
local dialog_sender_2 = { name=sender_2:character_name(), icon=sender_2:character_icon()}
|
||
|
|
||
|
send_dialog({
|
||
|
{sender=dialog_sender_1.name, icon=dialog_sender_1.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_2_stage_0_message_1")},
|
||
|
{sender=dialog_sender_2.name, icon=dialog_sender_2.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_2_stage_0_message_2")},
|
||
|
{sender=dialog_sender_1.name, icon=dialog_sender_1.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_2_stage_0_message_3")},
|
||
|
{sender=dialog_sender_2.name, icon=dialog_sender_2.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_2_stage_0_message_4")}
|
||
|
})
|
||
|
|
||
|
TASK_2_CACHE.stage_0_dialog_sent = true
|
||
|
end
|
||
|
|
||
|
tsk.stage = 1
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- Second stage : Go to the container warehouse and find clues as to what happened to the helicopter
|
||
|
if tsk.stage == 1 then
|
||
|
-- Retrieve the server object (they may not always exist - if they aren't spawned yet)
|
||
|
local helicopter_se = TASK_2_CACHE.stage_1_helicopter_id and alife_object(TASK_2_CACHE.stage_1_helicopter_id)
|
||
|
|
||
|
-- Retrieve the server objects (they may not always exist - if they aren't spawned yet)
|
||
|
local quest_item_1_se = western_goods_utils.server_object_by_sid("wg_act_1_task_2_quest_item_1")
|
||
|
local quest_item_2_se = western_goods_utils.server_object_by_sid("wg_act_1_task_2_quest_item_2")
|
||
|
|
||
|
-- Populate the bandit camp
|
||
|
if not TASK_2_CACHE.stage_1_bandits_spawned then
|
||
|
local se_squad_1 = spawn_squad("western_goods_act_1_task_2_bandit_1_squad", vector():set(-424.8,0,-339.4), 12910, 4469)
|
||
|
local se_squad_2 = spawn_squad("western_goods_act_1_task_2_bandit_2_squad", vector():set(-394.9,0,-386.9), 52206, 4470)
|
||
|
local se_squad_3 = spawn_squad("western_goods_act_1_task_2_bandit_3_squad", vector():set(-405,0,-344), 36889, 4469)
|
||
|
|
||
|
se_squad_1.scripted_target = "jup_a12"
|
||
|
se_squad_2.scripted_target = "jup_a12"
|
||
|
se_squad_3.scripted_target = "jup_a12"
|
||
|
|
||
|
TASK_2_CACHE.stage_1_bandits_spawned = true
|
||
|
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- Delete the old helicopter from the Water Processing Station in Zaton
|
||
|
if not TASK_2_CACHE.stage_1_wps_heli_released then
|
||
|
release_story_helicopter()
|
||
|
TASK_2_CACHE.stage_1_wps_heli_released = true
|
||
|
end
|
||
|
|
||
|
-- Spawn the helicopter and make it go towards Yanov station, then make it head to the container warehouse
|
||
|
if not TASK_2_CACHE.stage_1_helicopter_spawned then
|
||
|
helicopter_se = heli_spawn("western_goods_helicopter",vector():set(346.7,7,984.4),674394,4724)
|
||
|
|
||
|
TASK_2_CACHE.stage_1_heli_ready_timer = time_global() + CONST_TASK_2_HELI_DELAY
|
||
|
TASK_2_CACHE.stage_1_helicopter_id = helicopter_se.id
|
||
|
TASK_2_CACHE.stage_1_helicopter_spawned = true
|
||
|
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- Spawn the Gauss rifle if it hasn't been spawned yet
|
||
|
if not quest_item_1_se then
|
||
|
quest_item_1_se = alife_create("wg_act_1_task_2_quest_item_1",vector():set(-445,0.8,-356.8),1056,4818)
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 2 - Stage 1 - Quest item no 1 spawned %s", quest_item_1_se.id)
|
||
|
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- Spawn the note if it hasn't been spawned yet
|
||
|
if not quest_item_2_se then
|
||
|
quest_item_2_se = alife_create("wg_act_1_task_2_quest_item_2",vector():set(-446.9,1.2,-384.3),756,4818)
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 2 - Stage 1 - Quest item no 2 spawned %s", quest_item_2_se.id)
|
||
|
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- Send a message and set the helicopter to move to the player after 60 seconds
|
||
|
local timer = TASK_2_CACHE.stage_1_heli_ready_timer
|
||
|
if not timer or timer >= time_global() then return end
|
||
|
|
||
|
-- Send the helicopter to protect the player, and send a dialog to the player
|
||
|
if not TASK_2_CACHE.stage_1_helicopter_sent then
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 2 - Stage 1 - Helicopter moving to player...")
|
||
|
|
||
|
heli_register(TASK_2_CACHE.stage_1_helicopter_id,HELICOPTERS_MODES.PROTECT_ACTOR,nil)
|
||
|
|
||
|
local attack_key_str = western_goods_utils.get_key_translation(western_goods_mcm.get_config("heli_attack"))
|
||
|
|
||
|
-- Send a dialog to the player to inform him the helicopter is coming
|
||
|
local dialog_sender = {name="Mercenary helicopter", icon="ui_inGame2_PD_DownToEarth"}
|
||
|
|
||
|
send_dialog({
|
||
|
{sender=dialog_sender.name, icon=dialog_sender.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_2_stage_1_message_1",attack_key_str)}
|
||
|
})
|
||
|
|
||
|
TASK_2_CACHE.stage_1_helicopter_sent = true
|
||
|
end
|
||
|
|
||
|
-- If the player picked one of the items, isn't wearing a disguise, and hasn't been punished yet (punish the player only once, not every refresh...)
|
||
|
if not TASK_2_CACHE.stage_1_target_1_robbed and not (quest_item_1_se and quest_item_1_se.parent_id == 65535) then
|
||
|
|
||
|
local nearest_npc, nearest_npc_dist = utils_obj.get_nearest_stalker(db.actor)
|
||
|
|
||
|
-- Punish the player if he's not wearing a disguise, and a bandit is close to him
|
||
|
if nearest_npc_dist and nearest_npc:character_community() == "bandit" and nearest_npc_dist < 10 and not gameplay_disguise.is_actor_disguised() then
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 2 - Stage 1 - Nearest %s %s is %s m away", nearest_npc:character_community(), nearest_npc:section(), nearest_npc_dist)
|
||
|
|
||
|
-- Degrade player reputation
|
||
|
game_relations.change_faction_relations("bandit", get_actor_true_community(), CONST_TASK_2_REP_THEFT)
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 2 - Stage 1 - Player punished for stealing %s", CONST_TASK_2_REP_THEFT)
|
||
|
|
||
|
-- Make the npc send a message to the player
|
||
|
local dialog_sender = { name= nearest_npc:character_name(), icon= nearest_npc:character_icon()}
|
||
|
|
||
|
send_dialog({
|
||
|
{sender=dialog_sender.name, icon=dialog_sender.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_2_stage_1_message_3")}
|
||
|
},true)
|
||
|
end
|
||
|
|
||
|
-- Save that the item has been robbed (so that the player doesn't get punished if he gets exposed way later)
|
||
|
TASK_2_CACHE.stage_1_target_1_robbed = true
|
||
|
end
|
||
|
|
||
|
-- If the player picked one of the items, isn't wearing a disguise, and hasn't been punished yet (punish the player only once, not every refresh...)
|
||
|
if not TASK_2_CACHE.stage_1_target_2_robbed and not (quest_item_2_se and quest_item_2_se.parent_id == 65535) then
|
||
|
|
||
|
local nearest_npc, nearest_npc_dist = utils_obj.get_nearest_stalker(db.actor)
|
||
|
|
||
|
-- Punish the player if he's not wearing a disguise, and a bandit is close to him
|
||
|
if nearest_npc_dist and nearest_npc:character_community() == "bandit" and nearest_npc_dist < 10 and not gameplay_disguise.is_actor_disguised() then
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 2 - Stage 1 - Nearest %s %s is %s m away", nearest_npc:character_community(), nearest_npc:section(), nearest_npc_dist)
|
||
|
|
||
|
-- Degrade player reputation
|
||
|
game_relations.change_faction_relations("bandit", get_actor_true_community(), CONST_TASK_2_REP_THEFT)
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 2 - Stage 1 - Player punished for stealing %s", CONST_TASK_2_REP_THEFT)
|
||
|
|
||
|
-- Make the npc send a message to the player
|
||
|
local dialog_sender = { name= nearest_npc:character_name(), icon= nearest_npc:character_icon()}
|
||
|
|
||
|
send_dialog({
|
||
|
{sender=dialog_sender.name, icon=dialog_sender.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_2_stage_1_message_4")}
|
||
|
},true)
|
||
|
end
|
||
|
|
||
|
-- Save that the item has been robbed (so that the player doesn't get punished if he gets exposed way later)
|
||
|
TASK_2_CACHE.stage_1_target_2_robbed = true
|
||
|
end
|
||
|
|
||
|
-- If the player picked up both quest items, progress the task
|
||
|
if not (quest_item_1_se and quest_item_1_se.parent_id == 65535) and not (quest_item_2_se and quest_item_2_se.parent_id == 65535) then
|
||
|
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 2 - Stage 1 - Player picked up the items - %s - %s", quest_item_1_se.id, quest_item_2_se.id)
|
||
|
|
||
|
-- If the player is hostile to bandits, progress to stage 2, otherwise, progress to stage 3
|
||
|
if game_relations.is_factions_enemies(get_actor_true_community(), "bandit") and not gameplay_disguise.is_actor_disguised() then
|
||
|
|
||
|
-- Spawn the bandit reinforcements around the Container Warehouse area
|
||
|
if not TASK_2_CACHE.stage_2_bandit_squads_spawned then
|
||
|
local squad_1_se = spawn_squad("western_goods_act_1_task_2_bandit_4_squad", vector():set(-424.8,0,-339.4), 12910, 4469)
|
||
|
local squad_2_se = spawn_squad("western_goods_act_1_task_2_bandit_5_squad", vector():set(-394.9,0,-386.9), 52206, 4470)
|
||
|
local squad_3_se = spawn_squad("western_goods_act_1_task_2_bandit_6_squad", vector():set(-405,0,-344), 36889, 4469)
|
||
|
|
||
|
squad_1_se.scripted_target = "jup_a12"
|
||
|
squad_2_se.scripted_target = "jup_a12"
|
||
|
squad_3_se.scripted_target = "jup_a12"
|
||
|
|
||
|
-- Save the time the fight was started at, to indicate the targets after 2 in-game hours
|
||
|
TASK_2_CACHE.stage_2_show_targets_timer = time_global() + CONST_TASK_2_SHOW_TARGETS_DELAY
|
||
|
TASK_2_CACHE.stage_2_bandit_squads_spawned = true
|
||
|
|
||
|
-- Alert the player about the incoming bandits
|
||
|
local dialog_sender = {name="Mercenary helicopter", icon="ui_inGame2_PD_DownToEarth"}
|
||
|
|
||
|
send_dialog({
|
||
|
{sender=dialog_sender.name, icon=dialog_sender.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_2_stage_2_message_1")}
|
||
|
})
|
||
|
|
||
|
return
|
||
|
end
|
||
|
|
||
|
tsk.stage = 2
|
||
|
return
|
||
|
else
|
||
|
-- Return the helicopter to the processing station
|
||
|
heli_register(TASK_2_CACHE.stage_1_helicopter_id,HELICOPTERS_MODES.LEAVE_AT_POINT,vector():set(346.7,7,984.4))
|
||
|
|
||
|
-- Spawn a new one at the Water Processing Station
|
||
|
create_story_helicopter("wps")
|
||
|
|
||
|
-- Notify the player that the heli is leaving
|
||
|
local dialog_sender = {name="Mercenary helicopter", icon="ui_inGame2_PD_DownToEarth"}
|
||
|
|
||
|
send_dialog({
|
||
|
{sender=dialog_sender.name, icon=dialog_sender.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_2_stage_1_message_2")}
|
||
|
})
|
||
|
|
||
|
tsk.stage = 3
|
||
|
return
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Third stage : Face off the bandits reinforcements
|
||
|
if tsk.stage == 2 then
|
||
|
-- Retrieve the server objects (they may not always exist - if they aren't spawned yet or unavailable)
|
||
|
local squad_1_se = western_goods_utils.server_object_by_sid("western_goods_act_1_task_2_bandit_4_squad")
|
||
|
local squad_2_se = western_goods_utils.server_object_by_sid("western_goods_act_1_task_2_bandit_5_squad")
|
||
|
local squad_3_se = western_goods_utils.server_object_by_sid("western_goods_act_1_task_2_bandit_6_squad")
|
||
|
|
||
|
-- If all of the squads are dead, or the player is wearing a disguise
|
||
|
if (not squad_1_se and not squad_2_se and not squad_3_se) or gameplay_disguise.is_actor_disguised() then
|
||
|
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 2 - Stage 2 - Bandit squads cleared...")
|
||
|
|
||
|
-- Retrieve the game object (may not exist if the helicopter has been destroyed)
|
||
|
local helicopter_se = TASK_2_CACHE.stage_1_helicopter_id and alife_object(TASK_2_CACHE.stage_1_helicopter_id)
|
||
|
local helicopter_obj = helicopter_se and level_object_by_id(helicopter_se.id)
|
||
|
|
||
|
if helicopter_obj then
|
||
|
-- Return the helicopter to the processing station
|
||
|
heli_register(helicopter_obj:id(),HELICOPTERS_MODES.LEAVE_AT_POINT,vector():set(346.7,7,984.4))
|
||
|
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 2 - Stage 2 - Helicopter moving out to WPS...")
|
||
|
|
||
|
-- Inform the player that the helicopter is leaving
|
||
|
local dialog_sender = {name="Mercenary helicopter", icon="ui_inGame2_PD_DownToEarth"}
|
||
|
|
||
|
send_dialog({
|
||
|
{sender=dialog_sender.name, icon=dialog_sender.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_2_stage_2_message_2")}
|
||
|
})
|
||
|
end
|
||
|
|
||
|
-- And progress the task
|
||
|
tsk.stage = 3
|
||
|
return
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Fourth stage : Bring back the quest items
|
||
|
if tsk.stage == 3 then
|
||
|
-- Retrieve the server objects
|
||
|
local quest_item_1 = western_goods_utils.server_object_by_sid("wg_act_1_task_2_quest_item_1")
|
||
|
local quest_item_2 = western_goods_utils.server_object_by_sid("wg_act_1_task_2_quest_item_2")
|
||
|
|
||
|
-- Spawn the Gauss rifle if it disappeared
|
||
|
if not quest_item_1 then
|
||
|
quest_item_1 = alife_create("wg_act_1_task_2_quest_item_1",vector():set(-445,0.8,-356.8),1056,4818)
|
||
|
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 2 - Stage 3 - Quest item no 1 respawned %s", quest_item_1.id)
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- Spawn the note if it disappeared
|
||
|
if not quest_item_2 then
|
||
|
quest_item_2 = alife_create("wg_act_1_task_2_quest_item_2",vector():set(-446.9,1.2,-384.3),756,4818)
|
||
|
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 2 - Stage 3 - Quest item no 2 respawned %s", quest_item_2.id)
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- If the player picked up both quest items, progress to stage 4
|
||
|
if not (quest_item_1 and quest_item_1.parent_id ~= AC_ID) and not (quest_item_2 and quest_item_2.parent_id ~= AC_ID) then
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 2 - Stage 3 - Player picked up the items - %s - %s", quest_item_1.id, quest_item_2.id)
|
||
|
tsk.stage = 4
|
||
|
return
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Fifth stage : If one of the quest items are dropped, roll back to fourth stage
|
||
|
if tsk.stage == 4 then
|
||
|
-- Retrieve the server objects
|
||
|
local quest_item_1 = western_goods_utils.server_object_by_sid("wg_act_1_task_2_quest_item_1")
|
||
|
local quest_item_2 = western_goods_utils.server_object_by_sid("wg_act_1_task_2_quest_item_2")
|
||
|
|
||
|
if not western_goods_utils.has_info("western_goods_act_1_task_2_ready_finished") then
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 2 - Task ready to be completed...")
|
||
|
western_goods_utils.give_info("western_goods_act_1_task_2_ready_finished")
|
||
|
end
|
||
|
|
||
|
-- If the player dropped one of the quest items, rollback to stage 3
|
||
|
if (not quest_item_1 or quest_item_1 and quest_item_1.parent_id ~= AC_ID) or (not quest_item_2 or quest_item_2 and quest_item_2.parent_id ~= AC_ID) then
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 2 - Stage 4 - Player dropped the items - %s - %s", quest_item_1.id, quest_item_2.id)
|
||
|
|
||
|
if western_goods_utils.has_info("western_goods_act_1_task_2_ready_finished") then
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 2 - Task no longer ready to be completed...")
|
||
|
western_goods_utils.rem_info("western_goods_act_1_task_2_ready_finished")
|
||
|
end
|
||
|
|
||
|
tsk.stage = 3
|
||
|
return
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- ---------------------------------------------------------------------------------------------------------------------
|
||
|
-- TASK 3 - THE RESCUE
|
||
|
-- ---------------------------------------------------------------------------------------------------------------------
|
||
|
|
||
|
--- Function used to start Act 1, Task 3.
|
||
|
--- @param first_speaker cse_alife_object
|
||
|
--- @param second_speaker cse_alife_object
|
||
|
--- @return nil
|
||
|
function act_1_task_3_start(first_speaker, second_speaker)
|
||
|
local npc = dialogs.who_is_npc(first_speaker, second_speaker)
|
||
|
task_manager.get_task_manager():give_task("western_goods_act_1_task_3", npc:id())
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 3 - Task started...")
|
||
|
end
|
||
|
|
||
|
--- Function used to end Act 1, Task 3.
|
||
|
--- @return nil
|
||
|
function act_1_task_3_end()
|
||
|
task_manager.get_task_manager():set_task_completed("western_goods_act_1_task_3")
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 3 - Task completed...")
|
||
|
end
|
||
|
|
||
|
--- Function called when the task is initiated.
|
||
|
--- @param actor cse_alife_object
|
||
|
--- @param npc cse_alife_object
|
||
|
--- @return nil
|
||
|
function xr_effects.act_1_task_3_init(actor,npc)
|
||
|
-- Process info portions
|
||
|
western_goods_utils.give_info("western_goods_act_1_task_3_active")
|
||
|
western_goods_utils.give_info("western_goods_act_1_task_3_init")
|
||
|
end
|
||
|
|
||
|
--- Function called when the task is successfully completed.
|
||
|
--- @param actor cse_alife_object
|
||
|
--- @param npc cse_alife_object
|
||
|
--- @return nil
|
||
|
function xr_effects.act_1_task_3_complete(actor,npc)
|
||
|
-- Process info portions
|
||
|
western_goods_utils.rem_info("western_goods_act_1_task_3_active")
|
||
|
western_goods_utils.rem_info("western_goods_act_1_task_3_init")
|
||
|
western_goods_utils.give_info("western_goods_act_1_task_3_finished")
|
||
|
western_goods_utils.give_info("western_goods_act_1_finished")
|
||
|
|
||
|
-- Process reward
|
||
|
xr_effects.reward_random_money(actor,npc,{"10000","15000"})
|
||
|
xr_effects.complete_task_inc_goodwill(actor,npc,{"100","killer"})
|
||
|
end
|
||
|
|
||
|
--- Function called when the task is failed.
|
||
|
--- @param actor cse_alife_object
|
||
|
--- @param npc cse_alife_object
|
||
|
--- @return nil
|
||
|
function xr_effects.act_1_task_3_fail(actor,npc)
|
||
|
-- Process info portions
|
||
|
western_goods_utils.rem_info("western_goods_act_1_task_3_active")
|
||
|
western_goods_utils.rem_info("western_goods_act_1_task_3_init")
|
||
|
western_goods_utils.rem_info("western_goods_crew_member_rescue_over")
|
||
|
|
||
|
-- Process penalty
|
||
|
xr_effects.fail_task_dec_goodwill(actor,npc,{"35","killer"})
|
||
|
end
|
||
|
|
||
|
--- Function used to retrieve the title of the mission (displayed in the PDA).
|
||
|
--- @param task_id number
|
||
|
--- @param field string
|
||
|
--- @param p any
|
||
|
--- @param tsk CGameTask
|
||
|
--- @return string
|
||
|
function task_functor.act_1_task_3_title_f(task_id,field,p,tsk)
|
||
|
if true then -- Cond to force my IDE to fold this fucking function correctly
|
||
|
return western_goods_utils.get_translation("st_wg_act_1_task_3_title")
|
||
|
end
|
||
|
end
|
||
|
|
||
|
--- Function used to retrieve the description of the mission (displayed in the PDA).
|
||
|
--- Warning : naming contract on the translation string : st_wg_trader_act_1_task_3_stage_<stage>_descr.
|
||
|
--- @param task_id number
|
||
|
--- @param field string
|
||
|
--- @param p any
|
||
|
--- @param tsk CGameTask
|
||
|
--- @return string
|
||
|
function task_functor.act_1_task_3_descr_f(task_id,field,p,tsk)
|
||
|
if true then -- Cond to force my IDE to fold this fucking function correctly
|
||
|
return western_goods_utils.get_translation("st_wg_act_1_task_3_stage_" .. tostring(tsk.stage) .. "_descr")
|
||
|
end
|
||
|
end
|
||
|
|
||
|
--- Function used to retrieve the target of the mission (marker displayed (or not) in the PDA).
|
||
|
--- @param task_id number
|
||
|
--- @param field string
|
||
|
--- @param p any
|
||
|
--- @param tsk CGameTask
|
||
|
--- @return number
|
||
|
function task_functor.act_1_task_3_target_f(task_id,field,p,tsk)
|
||
|
if western_goods_utils.has_info("western_goods_act_1_task_3_init") then
|
||
|
if tsk.stage == 0 then
|
||
|
local crew_member_se = western_goods_utils.server_object_by_sid("stalker_crew_member")
|
||
|
return crew_member_se and crew_member_se.id
|
||
|
end
|
||
|
|
||
|
if tsk.stage == 1 then
|
||
|
local smart = SIMBOARD:get_smart_by_name("red_smart_terrain_bridge")
|
||
|
return smart and smart.id
|
||
|
end
|
||
|
|
||
|
if tsk.stage == 2 then
|
||
|
-- Wait 5 real life minutes before starting to indicate where the remaining enemies are
|
||
|
local timer = TASK_3_CACHE.stage_2_show_targets_timer
|
||
|
if timer and timer <= time_global() then
|
||
|
local squad_1_se = western_goods_utils.server_object_by_sid("western_goods_act_1_task_3_mono_bridge_1_squad")
|
||
|
local squad_2_se = western_goods_utils.server_object_by_sid("western_goods_act_1_task_3_mono_bridge_2_squad")
|
||
|
return (squad_1_se and squad_1_se.id) or (squad_2_se and squad_2_se.id)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if tsk.stage == 3 then
|
||
|
local smart = SIMBOARD:get_smart_by_name("red_smart_terrain_bridge")
|
||
|
return smart and smart.id
|
||
|
end
|
||
|
|
||
|
if tsk.stage == 4 then
|
||
|
return tsk.task_giver_id
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
--- Function used to manage the mission logic as a whole.
|
||
|
--- @param tsk CGameTask
|
||
|
--- @param task_id number
|
||
|
--- @return string
|
||
|
function task_status_functor.act_1_task_3_status_f(tsk,task_id)
|
||
|
if western_goods_utils.has_info("western_goods_act_1_task_3_init") then
|
||
|
-- First stage : Find and rescue the crew member
|
||
|
if tsk.stage == 0 then
|
||
|
-- Retrieve the server and game objects (they may not always exist - if they aren't spawned yet or unavailable)
|
||
|
local crew_member_se = western_goods_utils.server_object_by_sid("stalker_crew_member")
|
||
|
local crew_member_obj = crew_member_se and level_object_by_id(crew_member_se.id)
|
||
|
|
||
|
-- Retrieve the server and game objects (they may not always exist - if they aren't spawned yet or unavailable)
|
||
|
local crew_member_squad_se = western_goods_utils.server_object_by_sid("stalker_crew_member_squad")
|
||
|
|
||
|
-- Spawn the crew member squad
|
||
|
if not crew_member_squad_se then
|
||
|
crew_member_squad_se = spawn_story_squad("stalker_crew_member_squad", vector():set(35.3,1,42.9), SIMBOARD.smarts_by_names["lim_smart_terrain_6"])
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- Spawn monolith squads to guard the crew member
|
||
|
if not TASK_3_CACHE.stage_0_mono_guard_spawned then
|
||
|
local se_squad_1 = spawn_squad("western_goods_act_1_task_3_mono_guards_1_squad", vector():set(17.2,1,47.3), 35710, 2475)
|
||
|
local se_squad_2 = spawn_squad("western_goods_act_1_task_3_mono_guards_2_squad", vector():set(42,-3,50.4), 48878, 2475)
|
||
|
|
||
|
se_squad_1.scripted_target = "lim_smart_terrain_6"
|
||
|
se_squad_2.scripted_target = "lim_smart_terrain_6"
|
||
|
|
||
|
TASK_3_CACHE.stage_0_mono_guard_spawned = true
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- When the player has rescued the crew member, progress further
|
||
|
if not western_goods_utils.has_info("western_goods_crew_member_rescue_over") then return end
|
||
|
|
||
|
if crew_member_obj and not TASK_3_CACHE.stage_0_crew_member_companion then
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 3 - Stage 0 - Player rescued crew member...")
|
||
|
|
||
|
-- Add the crew member to the player squad
|
||
|
dialogs_axr_companion.become_actor_companion(db.actor,crew_member_obj)
|
||
|
|
||
|
TASK_3_CACHE.stage_0_crew_member_companion = true
|
||
|
end
|
||
|
|
||
|
-- Send a dialog between the player and the task giver
|
||
|
if not TASK_3_CACHE.stage_0_dialog_sent then
|
||
|
|
||
|
local sender_1 = alife():actor()
|
||
|
local sender_2 = alife_object(tsk.task_giver_id)
|
||
|
|
||
|
local dialog_sender_1 = { name=sender_1:character_name(), icon=sender_1:character_icon()}
|
||
|
local dialog_sender_2 = { name=sender_2:character_name(), icon=sender_2:character_icon()}
|
||
|
|
||
|
send_dialog({
|
||
|
{sender=dialog_sender_1.name, icon=dialog_sender_1.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_3_stage_0_message_1")},
|
||
|
{sender=dialog_sender_2.name, icon=dialog_sender_2.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_3_stage_0_message_2")},
|
||
|
{sender=dialog_sender_1.name, icon=dialog_sender_1.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_3_stage_0_message_3")},
|
||
|
{sender=dialog_sender_2.name, icon=dialog_sender_2.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_3_stage_0_message_4")},
|
||
|
{sender=dialog_sender_1.name, icon=dialog_sender_1.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_3_stage_0_message_5")}
|
||
|
})
|
||
|
|
||
|
TASK_3_CACHE.progress_timer = time_global() + CONST_TASK_3_PROGRESS_DELAY
|
||
|
TASK_3_CACHE.stage_0_dialog_sent = true
|
||
|
end
|
||
|
|
||
|
-- Progress the task
|
||
|
if TASK_3_CACHE.progress_timer < time_global() then
|
||
|
tsk.stage = 1
|
||
|
return
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Second stage : Get to the bridge in the Red Forest
|
||
|
if tsk.stage == 1 then
|
||
|
-- Retrieve the server and game objects
|
||
|
local crew_member_squad_se = western_goods_utils.server_object_by_sid("stalker_crew_member_squad")
|
||
|
|
||
|
-- Respawn the crew member squad
|
||
|
if not crew_member_squad_se then
|
||
|
crew_member_squad_se = spawn_story_squad("stalker_crew_member_squad", vector():set(35.3,1,42.9), SIMBOARD.smarts_by_names["lim_smart_terrain_6"])
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- Spawn the enemy squads at the bridge in the Red Forest, if they haven't already, or if they all died
|
||
|
if not TASK_3_CACHE.stage_1_mono_bridge_spawned then
|
||
|
-- Spawn the squads
|
||
|
local monolith_se_squad_1 = spawn_squad("western_goods_act_1_task_3_mono_bridge_1_squad", vector():set(-114,-0.6,-214.3), 8509, 2792)
|
||
|
local monolith_se_squad_2 = spawn_squad("western_goods_act_1_task_3_mono_bridge_2_squad", vector():set(-111.5,-0.6,-210.6), 8905, 2792)
|
||
|
|
||
|
monolith_se_squad_1.scripted_target = "red_smart_terrain_bridge"
|
||
|
monolith_se_squad_2.scripted_target = "red_smart_terrain_bridge"
|
||
|
|
||
|
TASK_3_CACHE.stage_1_mono_bridge_spawned = true
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- Wait for the player to be in Limansk
|
||
|
if level.name() == "l10_limansk" then
|
||
|
local player_pos = db.actor:position()
|
||
|
|
||
|
-- Positions of the smart terrains the player needs to reach to get a lore dump
|
||
|
local dialog_1_activation_pos = SIMBOARD:get_smart_by_name("lim_smart_terrain_5").position
|
||
|
local dialog_2_activation_pos = SIMBOARD:get_smart_by_name("lim_smart_terrain_3").position
|
||
|
local dialog_3_activation_pos = SIMBOARD:get_smart_by_name("lim_smart_terrain_1").position
|
||
|
|
||
|
-- Distances between the player and the smart terrains
|
||
|
local dist_to_dialog_1 = dialog_1_activation_pos and western_goods_utils.get_distance_sqr(player_pos, dialog_1_activation_pos)
|
||
|
local dist_to_dialog_2 = dialog_2_activation_pos and western_goods_utils.get_distance_sqr(player_pos, dialog_2_activation_pos)
|
||
|
local dist_to_dialog_3 = dialog_3_activation_pos and western_goods_utils.get_distance_sqr(player_pos, dialog_3_activation_pos)
|
||
|
|
||
|
-- Conditions for dialogs
|
||
|
local dialog_1_cond = dist_to_dialog_1 < CONST_TASK_3_DIALOG_DIST and not TASK_3_CACHE.stage_1_dialog_1_sent
|
||
|
local dialog_2_cond = dist_to_dialog_2 < CONST_TASK_3_DIALOG_DIST and not TASK_3_CACHE.stage_1_dialog_2_sent and TASK_3_CACHE.stage_1_dialog_1_sent
|
||
|
local dialog_3_cond = dist_to_dialog_3 < CONST_TASK_3_DIALOG_EX_DIST and not TASK_3_CACHE.stage_1_dialog_3_sent and TASK_3_CACHE.stage_1_dialog_2_sent
|
||
|
|
||
|
if dialog_1_cond then
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 3 - Stage 1 - Player reached dialog point 1...")
|
||
|
|
||
|
local sender_1 = alife():actor()
|
||
|
local sender_2 = western_goods_utils.server_object_by_sid("stalker_crew_member")
|
||
|
|
||
|
local dialog_sender_1 = { name=sender_1:character_name(), icon=sender_1:character_icon()}
|
||
|
local dialog_sender_2 = { name=sender_2:character_name(), icon=sender_2:character_icon()}
|
||
|
|
||
|
send_dialog({
|
||
|
{sender=dialog_sender_2.name, icon=dialog_sender_2.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_3_stage_1_message_1")},
|
||
|
{sender=dialog_sender_1.name, icon=dialog_sender_1.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_3_stage_1_message_2")}
|
||
|
})
|
||
|
|
||
|
TASK_3_CACHE.stage_1_dialog_1_sent = true
|
||
|
end
|
||
|
|
||
|
if dialog_2_cond then
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 3 - Stage 1 - Player reached dialog point 2...")
|
||
|
|
||
|
local sender_1 = alife():actor()
|
||
|
local sender_2 = western_goods_utils.server_object_by_sid("stalker_crew_member")
|
||
|
|
||
|
local dialog_sender_1 = { name=sender_1:character_name(), icon=sender_1:character_icon()}
|
||
|
local dialog_sender_2 = { name=sender_2:character_name(), icon=sender_2:character_icon()}
|
||
|
|
||
|
send_dialog({
|
||
|
{sender=dialog_sender_1.name, icon=dialog_sender_1.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_3_stage_1_message_3")},
|
||
|
{sender=dialog_sender_2.name, icon=dialog_sender_2.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_3_stage_1_message_4")},
|
||
|
{sender=dialog_sender_1.name, icon=dialog_sender_1.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_3_stage_1_message_5")},
|
||
|
{sender=dialog_sender_2.name, icon=dialog_sender_2.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_3_stage_1_message_6")}
|
||
|
})
|
||
|
|
||
|
TASK_3_CACHE.stage_1_dialog_2_sent = true
|
||
|
end
|
||
|
|
||
|
if dialog_3_cond then
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 3 - Stage 1 - Player reached dialog point 3...")
|
||
|
|
||
|
local sender_1 = alife():actor()
|
||
|
local sender_2 = western_goods_utils.server_object_by_sid("stalker_crew_member")
|
||
|
|
||
|
local dialog_sender_1 = { name=sender_1:character_name(), icon=sender_1:character_icon()}
|
||
|
local dialog_sender_2 = { name=sender_2:character_name(), icon=sender_2:character_icon()}
|
||
|
|
||
|
send_dialog({
|
||
|
{sender=dialog_sender_1.name, icon=dialog_sender_1.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_3_stage_1_message_7")},
|
||
|
{sender=dialog_sender_2.name, icon=dialog_sender_2.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_3_stage_1_message_8")},
|
||
|
{sender=dialog_sender_1.name, icon=dialog_sender_1.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_3_stage_1_message_9")},
|
||
|
{sender=dialog_sender_2.name, icon=dialog_sender_2.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_3_stage_1_message_10")}
|
||
|
})
|
||
|
|
||
|
TASK_3_CACHE.stage_1_dialog_3_sent = true
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Wait for the player to be in the Red Forest
|
||
|
if level.name() == "l10_red_forest" then
|
||
|
-- Retrieve the player and target positions
|
||
|
local player_pos = db.actor:position()
|
||
|
local objective_pos = SIMBOARD:get_smart_by_name("red_smart_terrain_bridge").position
|
||
|
|
||
|
-- Wait for the player to be closer than 100m from the bridge
|
||
|
if not objective_pos or western_goods_utils.get_distance_sqr(player_pos, objective_pos) > CONST_TASK_3_BRIDGE_DIST then return end
|
||
|
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 3 - Stage 1 - Player reached Read Forest's bridge to Limansk...")
|
||
|
|
||
|
-- Save the time to indicate the remaining enemies on the PDA 5 real-life mins later
|
||
|
TASK_3_CACHE.stage_2_show_targets_timer = time_global() + CONST_TASK_3_SHOW_TARGETS_DELAY
|
||
|
|
||
|
-- Progress the task
|
||
|
tsk.stage = 2
|
||
|
return
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Third stage : Fight off the enemy squads
|
||
|
if tsk.stage == 2 then
|
||
|
-- Retrieve the server objects (they may not always exist - if they aren't spawned yet or unavailable)
|
||
|
local monolith_se_squad_1 = western_goods_utils.server_object_by_sid("western_goods_act_1_task_3_mono_bridge_1_squad")
|
||
|
local monolith_se_squad_2 = western_goods_utils.server_object_by_sid("western_goods_act_1_task_3_mono_bridge_2_squad")
|
||
|
|
||
|
-- Retrieve the server objects
|
||
|
local crew_member_squad_se = western_goods_utils.server_object_by_sid("stalker_crew_member_squad")
|
||
|
|
||
|
-- Respawn the crew member squad
|
||
|
if not crew_member_squad_se then
|
||
|
crew_member_squad_se = spawn_story_squad("stalker_crew_member_squad", vector():set(35.3,1,42.9), SIMBOARD.smarts_by_names["lim_smart_terrain_6"])
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- Progress only when all enemy squads are dead
|
||
|
if monolith_se_squad_1 or monolith_se_squad_2 then return end
|
||
|
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 3 - Stage 2 - All Monolith squads dead...")
|
||
|
|
||
|
-- Progress the task
|
||
|
tsk.stage = 3
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- Fourth stage : Wait for the helicopter to pickup the rescued crew member
|
||
|
if tsk.stage == 3 then
|
||
|
-- Retrieve the server object of the rescue helicopter
|
||
|
local helicopter_se = TASK_3_CACHE.stage_3_helicopter_id and alife_object(TASK_3_CACHE.stage_3_helicopter_id)
|
||
|
local helicopter_obj = helicopter_se and level_object_by_id(helicopter_se.id)
|
||
|
|
||
|
-- Retrieve the server and game object of the crew member
|
||
|
local crew_member_se = western_goods_utils.server_object_by_sid("stalker_crew_member")
|
||
|
local crew_member_obj = crew_member_se and level_object_by_id(crew_member_se.id)
|
||
|
|
||
|
-- Retrieve the server and game object of the crew member's squad
|
||
|
local crew_member_squad_se = western_goods_utils.server_object_by_sid("stalker_crew_member_squad")
|
||
|
|
||
|
-- Define the helicopter spawn and landing positions
|
||
|
local heli_spawn_pos = vector():set(348.8,10.9,149.2)
|
||
|
local heli_landing_pos = vector():set(-188.7,5.3,-195.8)
|
||
|
|
||
|
-- Delete the old helicopter from the Water Processing Station in Zaton
|
||
|
if not TASK_3_CACHE.stage_3_wps_heli_released then
|
||
|
release_story_helicopter()
|
||
|
TASK_2_CACHE.stage_3_wps_heli_released = true
|
||
|
end
|
||
|
|
||
|
-- Spawn the helicopter and direct it to the landing zone
|
||
|
if not TASK_3_CACHE.stage_3_helicopter_spawned then
|
||
|
helicopter_se = heli_spawn("western_goods_helicopter",heli_spawn_pos,8256,2792)
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 3 - Stage 3 - Helicopter spawned %s", helicopter_se.id)
|
||
|
|
||
|
heli_register(helicopter_se.id,HELICOPTERS_MODES.LAND_AT_POINT, heli_landing_pos)
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 3 - Stage 3 - Helicopter moving to player...")
|
||
|
|
||
|
TASK_3_CACHE.stage_3_helicopter_id = helicopter_se.id
|
||
|
TASK_3_CACHE.stage_3_helicopter_spawned = true
|
||
|
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- If the evac helicopter was destroyed, fail the task
|
||
|
if helicopter_obj and helicopter_obj:get_helicopter():GetfHealth() <= 0 then
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 3 - Stage 3 - Helicopter was destroyed - task failed")
|
||
|
return "fail"
|
||
|
end
|
||
|
|
||
|
-- If the crew member hasn't extracted, and isn't alive, respawn him
|
||
|
if not crew_member_squad_se and not western_goods_utils.has_info("western_goods_act_1_task_3_crew_member_extracted") then
|
||
|
crew_member_squad_se = spawn_story_squad("stalker_crew_member_squad", vector():set(35.3,1,42.9), SIMBOARD.smarts_by_names["lim_smart_terrain_6"])
|
||
|
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- Send a dialog to the player to inform him the helicopter is coming
|
||
|
if not TASK_3_CACHE.stage_3_dialog_sent then
|
||
|
local sender_1 = alife():actor()
|
||
|
|
||
|
local dialog_sender_1 = { name=sender_1:character_name(), icon=sender_1:character_icon()}
|
||
|
local dialog_sender_2 = { name="Mercenary helicopter", icon="ui_inGame2_PD_DownToEarth"}
|
||
|
|
||
|
send_dialog({
|
||
|
{sender=dialog_sender_1.name, icon=dialog_sender_1.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_3_stage_3_message_1")},
|
||
|
{sender=dialog_sender_2.name, icon=dialog_sender_2.icon, message=western_goods_utils.get_translation("st_wg_trader_act_1_task_3_stage_3_message_2")}
|
||
|
})
|
||
|
|
||
|
TASK_3_CACHE.stage_3_dialog_sent = true
|
||
|
end
|
||
|
|
||
|
-- Get the distance between the helicopter and the landing zone, and wait for it to be smaller than 5m
|
||
|
local dist_to_landing = helicopter_obj and western_goods_utils.get_distance_sqr(helicopter_obj:position(), heli_landing_pos)
|
||
|
if (not dist_to_landing) or dist_to_landing and dist_to_landing > CONST_TASK_3_HELI_DIST then return end
|
||
|
|
||
|
-- Set the rescued companion to head towards the helicopter
|
||
|
if not TASK_3_CACHE.stage_3_evac_order_given then
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 3 - Stage 3 - Helicopter reached landing zone (dist:%s)", dist_to_landing)
|
||
|
|
||
|
-- Remove companion from player squad
|
||
|
axr_companions.remove_from_actor_squad(crew_member_obj)
|
||
|
|
||
|
-- Force the npc logic back in, because dialogs_axr_companion fails to restore it for some reason
|
||
|
xr_logic.set_new_scheme_and_logic(crew_member_obj,"beh","beh@get_to_heli","logic",nil,"scripts\\western_goods_crew_member.ltx")
|
||
|
|
||
|
crew_member_se.scripted_target = "red_smart_terrain_bridge"
|
||
|
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 3 - Stage 3 - Crew member freed and moving to helicopter...")
|
||
|
|
||
|
TASK_3_CACHE.stage_3_evac_order_given = true
|
||
|
end
|
||
|
|
||
|
-- Get the distance to the heli, and wait for it to be smaller than 5m
|
||
|
local dist_to_heli = crew_member_obj and western_goods_utils.get_distance_sqr(crew_member_obj:position(), heli_landing_pos)
|
||
|
if (not dist_to_heli) or dist_to_heli and dist_to_heli > CONST_TASK_3_NPC_DIST then return end
|
||
|
|
||
|
-- Extract the squad member
|
||
|
if not TASK_3_CACHE.stage_3_crew_member_extracted then
|
||
|
-- Release the squad member (as in he got in the helicopter)
|
||
|
alife_release(crew_member_se)
|
||
|
|
||
|
-- Give the info that the crew member was successfully extracted
|
||
|
western_goods_utils.give_info("western_goods_act_1_task_3_crew_member_extracted")
|
||
|
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 3 - Stage 3 - Crew member extracted...")
|
||
|
|
||
|
-- Make the heli leave the level
|
||
|
heli_register(helicopter_se.id,HELICOPTERS_MODES.LEAVE_AT_POINT,heli_spawn_pos)
|
||
|
|
||
|
-- Spawn a new one at the Water Processing Station
|
||
|
create_story_helicopter("wps")
|
||
|
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 3 - Stage 3 - Helicopter leaving to Book Store...")
|
||
|
|
||
|
TASK_3_CACHE.stage_3_crew_member_extracted = true
|
||
|
end
|
||
|
|
||
|
-- Progress the task
|
||
|
tsk.stage = 4
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- Fifth stage : Return for the reward
|
||
|
if tsk.stage == 4 then
|
||
|
local crew_member_squad_se = western_goods_utils.server_object_by_sid("stalker_crew_member_squad")
|
||
|
|
||
|
if not western_goods_utils.has_info("western_goods_act_1_task_3_ready_finished") then
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 3 - Task ready to be completed...")
|
||
|
western_goods_utils.give_info("western_goods_act_1_task_3_ready_finished")
|
||
|
end
|
||
|
|
||
|
-- Spawn the rescued crew member in the book store
|
||
|
if not crew_member_squad_se then
|
||
|
crew_member_squad_se = spawn_squad("stalker_crew_member_squad", vector():set(-182.1,0.6,-343.9), 33349, 5019)
|
||
|
crew_member_squad_se.scripted_target = "pri_a18_smart_terrain"
|
||
|
return
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- ---------------------------------------------------------------------------------------------------------------------
|
||
|
-- Callbacks registration
|
||
|
-- ---------------------------------------------------------------------------------------------------------------------
|
||
|
|
||
|
--- Function used to register callbacks.
|
||
|
--- @return nil
|
||
|
function on_game_start()
|
||
|
RegisterScriptCallback("save_state", save_state)
|
||
|
RegisterScriptCallback("load_state", load_state)
|
||
|
RegisterScriptCallback("actor_on_first_update", task_2_setup)
|
||
|
RegisterScriptCallback("actor_on_first_update", task_3_setup)
|
||
|
end
|
||
|
|
||
|
-- ---------------------------------------------------------------------------------------------------------------------
|
||
|
-- Data persistence
|
||
|
-- ---------------------------------------------------------------------------------------------------------------------
|
||
|
|
||
|
--- Function used to store information in the save file.
|
||
|
--- @param m_data table
|
||
|
--- @return nil
|
||
|
function save_state(m_data)
|
||
|
-- Prepare save tables
|
||
|
local TASK_1_SAVE = {}
|
||
|
local TASK_2_SAVE = {}
|
||
|
local TASK_3_SAVE = {}
|
||
|
|
||
|
-- Make copies of task caches
|
||
|
copy_table(TASK_1_SAVE, TASK_1_CACHE)
|
||
|
copy_table(TASK_2_SAVE, TASK_2_CACHE)
|
||
|
copy_table(TASK_3_SAVE, TASK_3_CACHE)
|
||
|
|
||
|
-- Pre-process tables
|
||
|
TASK_1_SAVE.progress_timer = (TASK_1_SAVE.progress_timer or 0) - time_global()
|
||
|
TASK_2_SAVE.available_time = (TASK_2_SAVE.available_time or 0) - time_global()
|
||
|
TASK_3_SAVE.available_time = (TASK_3_SAVE.available_time or 0) - time_global()
|
||
|
TASK_3_SAVE.progress_timer = (TASK_3_SAVE.progress_timer or 0) - time_global()
|
||
|
TASK_2_SAVE.stage_1_heli_ready_timer = (TASK_2_SAVE.stage_1_heli_ready_timer or 0) - time_global()
|
||
|
TASK_2_SAVE.stage_2_show_targets_timer = (TASK_2_SAVE.stage_2_show_targets_timer or 0) - time_global()
|
||
|
TASK_3_SAVE.stage_2_show_targets_timer = (TASK_3_SAVE.stage_2_show_targets_timer or 0) - time_global()
|
||
|
|
||
|
-- Save tables
|
||
|
m_data.wg_act_1_task_1_cache = TASK_1_SAVE
|
||
|
m_data.wg_act_1_task_2_cache = TASK_2_SAVE
|
||
|
m_data.wg_act_1_task_3_cache = TASK_3_SAVE
|
||
|
|
||
|
-- Debug prints
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 1 - Saved variables...\n%s",utils_data.print_table(TASK_1_SAVE, false, true))
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 2 - Saved variables...\n%s",utils_data.print_table(TASK_2_SAVE, false, true))
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 3 - Saved variables...\n%s",utils_data.print_table(TASK_3_SAVE, false, true))
|
||
|
end
|
||
|
|
||
|
--- Function used to load information stored in the save file.
|
||
|
--- @param m_data table
|
||
|
--- @return nil
|
||
|
function load_state(m_data)
|
||
|
-- Retrieve save tables
|
||
|
local TASK_1_SAVE = m_data.wg_act_1_task_1_cache or {}
|
||
|
local TASK_2_SAVE = m_data.wg_act_1_task_2_cache or {}
|
||
|
local TASK_3_SAVE = m_data.wg_act_1_task_3_cache or {}
|
||
|
|
||
|
-- Post-process tables
|
||
|
TASK_1_SAVE.progress_timer = (TASK_1_SAVE.progress_timer or 0) + time_global()
|
||
|
TASK_2_SAVE.available_time = (TASK_2_SAVE.available_time or 0) + time_global()
|
||
|
TASK_3_SAVE.available_time = (TASK_3_SAVE.available_time or 0) + time_global()
|
||
|
TASK_3_SAVE.progress_timer = (TASK_3_SAVE.progress_timer or 0) + time_global()
|
||
|
TASK_2_SAVE.stage_1_heli_ready_timer = (TASK_2_SAVE.stage_1_heli_ready_timer or 0) + time_global()
|
||
|
TASK_2_SAVE.stage_2_show_targets_timer = (TASK_2_SAVE.stage_2_show_targets_timer or 0) + time_global()
|
||
|
TASK_3_SAVE.stage_2_show_targets_timer = (TASK_3_SAVE.stage_2_show_targets_timer or 0) + time_global()
|
||
|
|
||
|
-- Restore task caches
|
||
|
copy_table(TASK_1_CACHE, TASK_1_SAVE)
|
||
|
copy_table(TASK_2_CACHE, TASK_2_SAVE)
|
||
|
copy_table(TASK_3_CACHE, TASK_3_SAVE)
|
||
|
|
||
|
-- Debug prints
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 1 - Loaded variables...\n%s",utils_data.print_table(TASK_1_CACHE, false, true))
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 2 - Loaded variables...\n%s",utils_data.print_table(TASK_2_CACHE, false, true))
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 3 - Loaded variables...\n%s",utils_data.print_table(TASK_3_CACHE, false, true))
|
||
|
end
|
||
|
|
||
|
-- ---------------------------------------------------------------------------------------------------------------------
|
||
|
-- General functions
|
||
|
-- ---------------------------------------------------------------------------------------------------------------------
|
||
|
|
||
|
--- Function used to setup the automatic start of Act 2, Task 2.
|
||
|
--- @return nil
|
||
|
function task_2_setup()
|
||
|
-- Conditions
|
||
|
local task_1_done = western_goods_utils.has_info("western_goods_act_1_task_1_finished")
|
||
|
local task_2_started = western_goods_utils.has_info("western_goods_act_1_task_2_active")
|
||
|
local task_2_done = western_goods_utils.has_info("western_goods_act_1_task_2_finished")
|
||
|
local timeout_ready = time_global() > (TASK_2_CACHE.available_time or 0)
|
||
|
|
||
|
-- If the task is available
|
||
|
if not task_1_done or task_2_started or task_2_done then return end
|
||
|
|
||
|
-- If the task should be set up
|
||
|
if timeout_ready then
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 2 - Task set up...")
|
||
|
western_goods_utils.give_info("western_goods_act_1_task_2_available")
|
||
|
else
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 2 - What's missing? timeout_ready:%s (%s/%s)", timeout_ready, time_global(), TASK_2_CACHE.available_time)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function task_3_setup()
|
||
|
-- Conditions
|
||
|
local task_2_done = western_goods_utils.has_info("western_goods_act_1_task_2_finished")
|
||
|
local task_3_started = western_goods_utils.has_info("western_goods_act_1_task_3_active")
|
||
|
local task_3_done = western_goods_utils.has_info("western_goods_act_1_task_3_finished")
|
||
|
local timeout_ready = time_global() > (TASK_3_CACHE.available_time or 0)
|
||
|
|
||
|
-- If the task is available
|
||
|
if not task_2_done or task_3_started or task_3_done then return end
|
||
|
|
||
|
-- If the task should be set up
|
||
|
if timeout_ready then
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 3 - Task set up...")
|
||
|
western_goods_utils.give_info("western_goods_act_1_task_3_available")
|
||
|
else
|
||
|
dbg_printf("[WG] Tasks Act 1 | Task 3 - What's missing? timeout_ready:%s (%s/%s)", timeout_ready, time_global(), TASK_3_CACHE.available_time)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
--- Function used to give the player an item at the start of Act 1, Task 1.
|
||
|
--- Warning : This function should be called while a dialog is running.
|
||
|
--- @param first_speaker cse_alife_object
|
||
|
--- @param second_speaker cse_alife_object
|
||
|
--- @return nil
|
||
|
function task_1_give_item(first_speaker, second_speaker)
|
||
|
dialogs.relocate_item_section_to_actor(first_speaker, second_speaker, "wg_gps")
|
||
|
end
|
||
|
|
||
|
--- Function used to spawn a static helicopter at the Waste Processing Station if it doesn't exist.
|
||
|
--- @param location string
|
||
|
--- @return boolean
|
||
|
function create_story_helicopter(location)
|
||
|
local const_sec = "western_goods_helicopter_landed"
|
||
|
|
||
|
if not western_goods_utils.server_object_by_sid(const_sec) then
|
||
|
|
||
|
local pos, lvid, gvid
|
||
|
|
||
|
if location == "zaton" then
|
||
|
pos = vector():set(-4.5,-7,536.8)
|
||
|
lvid = 676572
|
||
|
gvid = 4330
|
||
|
elseif location == "wps" then
|
||
|
pos = vector():set(284.1,28.1,-364)
|
||
|
lvid = 1598393
|
||
|
gvid = 4454
|
||
|
else
|
||
|
printf("![WG] ERROR | Tasks Act 1 | Invalid spawn location for %s : loc:%s", const_sec, location)
|
||
|
return false
|
||
|
end
|
||
|
|
||
|
local heli_se = alife_create(const_sec,pos,lvid,gvid)
|
||
|
|
||
|
if heli_se then
|
||
|
dbg_printf("[WG] Tasks Act 1 | Created %s(%s) at loc:%s x:%s,y:%s,z:%s lvid:%s gvid:%s", const_sec, heli_se.id, location, pos.x, pos.y, pos.z, lvid, gvid)
|
||
|
return true
|
||
|
else
|
||
|
printf("![WG] ERROR | Tasks Act 1 | Failed to create %s at loc:%s x:%s,y:%s,z:%s lvid:%s gvid:%s", const_sec, location, pos.x, pos.y, pos.z, lvid, gvid)
|
||
|
return false
|
||
|
end
|
||
|
end
|
||
|
|
||
|
return false
|
||
|
end
|
||
|
|
||
|
--- Function used to release the helicopter at the Waste Processing Station if it exists.
|
||
|
--- @return nil
|
||
|
function release_story_helicopter()
|
||
|
local wps_heli_se = western_goods_utils.server_object_by_sid("western_goods_helicopter_landed")
|
||
|
if wps_heli_se then
|
||
|
alife_release(wps_heli_se)
|
||
|
|
||
|
dbg_printf("[WG] Tasks Act 1 | Released western_goods_helicopter_landed(%s)", wps_heli_se.id)
|
||
|
return true
|
||
|
end
|
||
|
|
||
|
return false
|
||
|
end
|
||
|
|
||
|
--- Function used to give the player a reward for finishing act 1.
|
||
|
--- Warning : This function should be called while a dialog is running.
|
||
|
--- @param first_speaker cse_alife_object
|
||
|
--- @param second_speaker cse_alife_object
|
||
|
--- @return nil
|
||
|
function give_final_reward(first_speaker, second_speaker)
|
||
|
dialogs.relocate_item_section_to_actor(first_speaker, second_speaker, "af_compass_af_aam")
|
||
|
end
|