---==================================================================================================================--- --- --- --- 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 third act of the addon's storyline. --- --- --- --- Each task is composed of the following elements : --- --- - A act_3_task_X_start(...) function, used to start the task; --- --- - A act_3_task_X_end(...) function, used to end the task; --- --- - A xr_effects.act_3_task_X_init(...) function, called when the task has started; --- --- - A xr_effects.act_3_task_X_complete(...) function, called when the task was successfully completed; --- --- - A xr_effects.act_3_task_X_fail(...) function, called when the task was failed; --- --- - A task_functor.act_3_task_X_title_f(...) function, called periodically to get the name; --- --- - A task_functor.act_3_task_X_descr_f(...) function, called periodically to get the description; --- --- - A task_functor.act_3_task_X_target_f(...) function, called periodically to get the target (for the PDA); --- --- - A task_status_functor.act_3_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 send_dialog = western_goods_dialogs_manager.send_dialog -- Constants local CONST_TASK_1_USB_UNLOCK_DIALOG_ID = "western_goods_act_3_task_1_usb_unlock" local CONST_TASK_1_USB_UNLOCK_COST = 5000 local CONST_TASK_3_BRIBE_COST = 20000 -- Task variables TASK_1_CACHE = {} TASK_2_CACHE = {} TASK_3_CACHE = {} TASK_4_CACHE = {} -- --------------------------------------------------------------------------------------------------------------------- -- ACT 3 - CHERNENKO BROTHERS -- --------------------------------------------------------------------------------------------------------------------- -- TASK 1 - OLD STASH -- --------------------------------------------------------------------------------------------------------------------- --- Function used to start Act 3, Task 1. --- @param first_speaker cse_alife_object --- @param second_speaker cse_alife_object --- @return nil function act_3_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_3_task_1", npc:id()) dbg_printf("[WG] Tasks Act 3 | Task 1 - Task started...") end --- Function used to end Act 3, Task 1. --- @return nil function act_3_task_1_end() task_manager.get_task_manager():set_task_completed("western_goods_act_3_task_1") dbg_printf("[WG] Tasks Act 3 | 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_3_task_1_init(actor,npc) -- Process info portions western_goods_utils.give_info("western_goods_act_3_task_1_active") western_goods_utils.give_info("western_goods_act_3_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_3_task_1_complete(actor,npc) -- Process info portions western_goods_utils.rem_info("western_goods_act_3_task_1_active") western_goods_utils.rem_info("western_goods_act_3_task_1_init") western_goods_utils.give_info("western_goods_act_3_task_1_finished") end --- Function called when the task is failed. --- @param actor cse_alife_object --- @param npc cse_alife_object --- @return nil function xr_effects.act_3_task_1_fail(actor,npc) -- Process info portions western_goods_utils.rem_info("western_goods_act_3_task_1_active") western_goods_utils.rem_info("western_goods_act_3_task_1_init") -- 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_3_task_1_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_3_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_3_task_1_stage__descr. --- @param task_id number --- @param field string --- @param p any --- @param tsk CGameTask --- @return string function task_functor.act_3_task_1_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_3_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_3_task_1_target_f(task_id,field,p,tsk) if western_goods_utils.has_info("western_goods_act_3_task_1_init") then if tsk.stage == 0 then if western_goods_mcm.get_config("guided_tasks") then local usb_se = western_goods_utils.server_object_by_sid("wg_danylo_pendrive_quest_item") return usb_se and usb_se.id end end if tsk.stage == 1 then local usb_se = western_goods_utils.server_object_by_sid("wg_danylo_pendrive_quest_item") return usb_se and usb_se.id end if tsk.stage == 2 then return nil end if tsk.stage == 3 then if western_goods_mcm.get_config("guided_tasks") then local squad_se = western_goods_utils.server_object_by_sid("stalker_danylo_chernenko_squad") return squad_se and squad_se.id end 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_3_task_1_status_f(tsk,task_id) if western_goods_utils.has_info("western_goods_act_3_task_1_init") then -- First stage : Find the USB drive if tsk.stage == 0 then local usb_se = western_goods_utils.server_object_by_sid("wg_danylo_pendrive_quest_item") -- Spawn/respawn quest item if it doesn't exist if not usb_se then usb_se = alife_create_item("wg_danylo_pendrive_quest_item", task_1_get_spawn_stash()) dbg_printf("[WG] Tasks Act 3 | Task 1 - Stage 0 - Primary item spawned %s", usb_se.id) return end -- If the player picked up the supplies, progress to stage 3 if usb_se and usb_se.parent_id == AC_ID then -- Spawn Danylo if not western_goods_utils.server_object_by_sid("stalker_danylo_chernenko_squad") then western_goods_utils.spawn_squad_smart("stalker_danylo_chernenko_squad", "jup_a6") end -- Spawn SSU prisoner if not western_goods_utils.server_object_by_sid("western_goods_ssu_prisoner_squad") then western_goods_utils.spawn_squad_smart("western_goods_ssu_prisoner_squad", "jup_a6") end dbg_printf("[WG] Tasks Act 3 | Task 1 - Stage 0 - Player picked up the primary item %s", usb_se.id) tsk.stage = 2 return end end -- Second stage : Get the USB drive if tsk.stage == 1 then local usb_se = western_goods_utils.server_object_by_sid("wg_danylo_pendrive_quest_item") -- Respawn Danylo if he disappeared if not western_goods_utils.server_object_by_sid("stalker_danylo_chernenko_squad") then western_goods_utils.spawn_squad_smart("stalker_danylo_chernenko_squad", "jup_a6") end -- Respawn SSU prisoner if he disappeared if not western_goods_utils.server_object_by_sid("western_goods_ssu_prisoner_squad") then western_goods_utils.spawn_squad_smart("western_goods_ssu_prisoner_squad", "jup_a6") end -- Respawn quest item if it doesn't exist if not usb_se then usb_se = alife_create_item("wg_danylo_pendrive_quest_item", task_1_get_spawn_stash()) dbg_printf("[WG] Tasks Act 3 | Task 1 - Stage 1 - Primary item respawned %s", usb_se.id) return end if usb_se and usb_se.parent_id == AC_ID then dbg_printf("[WG] Tasks Act 3 | Task 1 - Stage 1 - Player picked up the primary item %s", usb_se.id) tsk.stage = 2 return end end -- Second stage : Access information if tsk.stage == 2 then local usb_se = western_goods_utils.server_object_by_sid("wg_danylo_pendrive_quest_item") -- Respawn Danylo if he disappeared if not western_goods_utils.server_object_by_sid("stalker_danylo_chernenko_squad") then western_goods_utils.spawn_squad_smart("stalker_danylo_chernenko_squad", "jup_a6") end -- Respawn SSU prisoner if he disappeared if not western_goods_utils.server_object_by_sid("western_goods_ssu_prisoner_squad") then western_goods_utils.spawn_squad_smart("western_goods_ssu_prisoner_squad", "jup_a6") end if usb_se and usb_se.parent_id ~= AC_ID then dbg_printf("[WG] Tasks Act 3 | Task 1 - Stage 2 - Player dropped the primary item %s", usb_se.id) tsk.stage = 1 return end western_goods_utils.give_info("western_goods_act_3_task_1_ready_finished") if ui_pda_encyclopedia_tab.is_unlocked_note("encyclopedia__notes_western_goods_hand_drawn_map") then dbg_printf("[WG] Tasks Act 3 | Task 1 - Stage 2 - Player unlocked Danylo's note...") tsk.stage = 3 return end end -- Second stage : Meet with Danylo if tsk.stage == 3 then -- Respawn Danylo if he disappeared if not western_goods_utils.server_object_by_sid("stalker_danylo_chernenko_squad") then western_goods_utils.spawn_squad_smart("stalker_danylo_chernenko_squad", "jup_a6") end -- Respawn SSU prisoner if he disappeared if not western_goods_utils.server_object_by_sid("western_goods_ssu_prisoner_squad") then western_goods_utils.spawn_squad_smart("western_goods_ssu_prisoner_squad", "jup_a6") end end end end -- --------------------------------------------------------------------------------------------------------------------- -- TASK 2 - PURSUERS -- --------------------------------------------------------------------------------------------------------------------- --- Function used to start Act 3, Task 2. --- @param first_speaker cse_alife_object --- @param second_speaker cse_alife_object --- @return nil function act_3_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_3_task_2", npc:id()) dbg_printf("[WG] Tasks Act 3 | Task 2 - Task started...") end --- Function used to end Act 3, Task 2. --- @return nil function act_3_task_2_end() task_manager.get_task_manager():set_task_completed("western_goods_act_3_task_2") dbg_printf("[WG] Tasks Act 3 | 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_3_task_2_init(actor,npc) -- Process info portions western_goods_utils.give_info("western_goods_act_3_task_2_active") western_goods_utils.give_info("western_goods_act_3_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_3_task_2_complete(actor,npc) -- Process info portions western_goods_utils.rem_info("western_goods_act_3_task_2_active") western_goods_utils.rem_info("western_goods_act_3_task_2_init") western_goods_utils.give_info("western_goods_act_3_task_2_finished") -- Process quest items xr_effects.remove_item(actor, npc, {"wg_deployment_notice_quest_item"}) end --- Function called when the task is failed. --- @param actor cse_alife_object --- @param npc cse_alife_object --- @return nil function xr_effects.act_3_task_2_fail(actor,npc) -- Process info portions western_goods_utils.rem_info("western_goods_act_3_task_2_active") western_goods_utils.rem_info("western_goods_act_3_task_2_init") -- 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_3_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_3_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_3_task_2_stage__descr. --- @param task_id number --- @param field string --- @param p any --- @param tsk CGameTask --- @return string function task_functor.act_3_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_3_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_3_task_2_target_f(task_id,field,p,tsk) if western_goods_utils.has_info("western_goods_act_3_task_2_init") then if tsk.stage == 0 then local squad_se = western_goods_utils.server_object_by_sid("western_goods_ssu_prisoner_squad") return squad_se and squad_se.id end if tsk.stage == 1 then local score = TASK_2_CACHE.interrogation_points or 0 local squad_se = western_goods_utils.server_object_by_sid("western_goods_ssu_bounty_squad") return score >= 0 and squad_se and squad_se.id or nil end if tsk.stage == 2 then if western_goods_mcm.get_config("guided_tasks") then local document_se = western_goods_utils.server_object_by_sid("wg_deployment_notice_quest_item") return document_se and document_se.parent_id end end if tsk.stage == 3 then local document_se = western_goods_utils.server_object_by_sid("wg_deployment_notice_quest_item") return document_se and document_se.id end if tsk.stage == 4 then local squad_se = western_goods_utils.server_object_by_sid("stalker_danylo_chernenko_squad") return squad_se and squad_se.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_3_task_2_status_f(tsk,task_id) if western_goods_utils.has_info("western_goods_act_3_task_2_init") then -- First stage : Interrogate the SSU prisoner if tsk.stage == 0 then -- Respawn SSU prisoner if he disappeared if not western_goods_utils.server_object_by_sid("western_goods_ssu_prisoner_squad") then western_goods_utils.spawn_squad_smart("western_goods_ssu_prisoner_squad", "jup_a6") end -- Wait for interrogation to be done (failsafe, task_2_interrogation_over should run before this) if not western_goods_utils.has_info("western_goods_ssu_prisoner_interrogated") then return end -- Spawn quest item (and squad) if not western_goods_utils.server_object_by_sid("wg_deployment_notice_quest_item") then local squad_se = task_2_spawn_bounty_squad() local document_se = task_2_spawn_quest_item(squad_se) end dbg_printf("[WG] Tasks Act 3 | Task 2 - Stage 0 - Player finished interrogation (failsafe)...") tsk.stage = 1 end -- First stage : Find and kill the bounty squad if tsk.stage == 1 then local squad_se = western_goods_utils.server_object_by_sid("western_goods_ssu_bounty_squad") local document_se = western_goods_utils.server_object_by_sid("wg_deployment_notice_quest_item") -- Spawn quest item in squad (and respawn squad if they died and quest item disappeared) if not document_se then squad_se = squad_se or task_2_spawn_bounty_squad() document_se = task_2_spawn_quest_item(squad_se) return end if not squad_se then dbg_printf("[WG] Tasks Act 3 | Task 2 - Stage 1 - SSU bounty squad is dead...") tsk.stage = 2 end end -- First stage : Investigate the bodies if tsk.stage == 2 then local document_se = western_goods_utils.server_object_by_sid("wg_deployment_notice_quest_item") -- Respawn quest item in respawn and respawn squad if not document_se then local squad_se = task_2_spawn_bounty_squad() document_se = task_2_spawn_quest_item(squad_se) return end if document_se and document_se.parent_id == AC_ID then local prisoner_squad_se = western_goods_utils.server_object_by_sid("western_goods_ssu_prisoner_squad") -- Remove SSU prisoner if prisoner_squad_se then SIMBOARD:remove_squad(prisoner_squad_se) dbg_printf("[WG] Tasks Act 3 | Task 2 - Stage 2 - Removed SSU prisoner squad...") end -- Teleport Danylo to new place if not TASK_2_CACHE.danylo_message_sent then local sender_1 = alife():actor() local sender_2 = western_goods_utils.server_object_by_sid("stalker_danylo_chernenko") send_dialog({ {sender=sender_2:character_name(), icon=sender_2:character_icon(), message=western_goods_utils.get_translation("st_wg_act_3_task_2_stage_2_message_1",sender_1:character_name())}, {sender=sender_1:character_name(), icon=sender_1:character_icon(), message=western_goods_utils.get_translation("st_wg_act_3_task_2_stage_2_message_2")}, }) western_goods_utils.give_info("western_goods_danylo_red_forest") dbg_printf("[WG] Tasks Act 3 | Task 2 - Stage 2 - Teleported Danylo squad...") TASK_2_CACHE.danylo_message_sent = true end dbg_printf("[WG] Tasks Act 3 | Task 2 - Stage 2 - Player picked up the primary item %s", document_se.id) tsk.stage = 4 end end -- First stage : Get the deployment notice if tsk.stage == 3 then local document_se = western_goods_utils.server_object_by_sid("wg_deployment_notice_quest_item") -- Respawn quest item in respawn and respawn squad if not document_se then local squad_se = task_2_spawn_bounty_squad() document_se = task_2_spawn_quest_item(squad_se) return end -- Respawn Danylo if he disappeared if not western_goods_utils.server_object_by_sid("stalker_danylo_chernenko_squad") then western_goods_utils.spawn_squad_smart("stalker_danylo_chernenko_squad", "red_smart_terrain_monsters_2") end if document_se and document_se.parent_id == AC_ID then dbg_printf("[WG] Tasks Act 3 | Task 2 - Stage 3 - Player picked up the primary item %s", document_se.id) tsk.stage = 4 end end -- First stage : Return the deployment notice if tsk.stage == 4 then local document_se = western_goods_utils.server_object_by_sid("wg_deployment_notice_quest_item") -- Respawn Danylo if he disappeared if not western_goods_utils.server_object_by_sid("stalker_danylo_chernenko_squad") then western_goods_utils.spawn_squad_smart("stalker_danylo_chernenko_squad", "red_smart_terrain_monsters_2") end western_goods_utils.give_info("western_goods_act_3_task_2_ready_finished") if document_se and document_se.parent_id ~= AC_ID then dbg_printf("[WG] Tasks Act 3 | Task 2 - Stage 4 - Player dropped up the primary item %s", document_se.id) western_goods_utils.rem_info("western_goods_act_3_task_2_ready_finished") tsk.stage = 3 end end end end -- --------------------------------------------------------------------------------------------------------------------- -- TASK 3 - HEAD OF OPERATIONS -- --------------------------------------------------------------------------------------------------------------------- --- Function used to start Act 3, Task 3. --- @param first_speaker cse_alife_object --- @param second_speaker cse_alife_object --- @return nil function act_3_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_3_task_3", npc:id()) dbg_printf("[WG] Tasks Act 3 | Task 3 - Task started...") end --- Function used to end Act 3, Task 3. --- @return nil function act_3_task_3_end() task_manager.get_task_manager():set_task_completed("western_goods_act_3_task_3") dbg_printf("[WG] Tasks Act 3 | 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_3_task_3_init(actor,npc) -- Process info portions western_goods_utils.give_info("western_goods_act_3_task_3_active") western_goods_utils.give_info("western_goods_act_3_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_3_task_3_complete(actor,npc) -- Process info portions western_goods_utils.rem_info("western_goods_act_3_task_3_active") western_goods_utils.rem_info("western_goods_act_3_task_3_init") western_goods_utils.give_info("western_goods_act_3_task_3_finished") end --- Function called when the task is failed. --- @param actor cse_alife_object --- @param npc cse_alife_object --- @return nil function xr_effects.act_3_task_3_fail(actor,npc) -- Process info portions western_goods_utils.rem_info("western_goods_act_3_task_3_active") western_goods_utils.rem_info("western_goods_act_3_task_3_init") -- 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_3_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_3_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_3_task_3_stage__descr. --- @param task_id number --- @param field string --- @param p any --- @param tsk CGameTask --- @return string function task_functor.act_3_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_3_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_3_task_3_target_f(task_id,field,p,tsk) if western_goods_utils.has_info("western_goods_act_3_task_3_init") then if tsk.stage == 0 then local squad_se = western_goods_utils.server_object_by_sid("western_goods_ssu_supervisor_squad") return squad_se and squad_se.id end if tsk.stage == 1 then local squad_se = western_goods_utils.server_object_by_sid("stalker_danylo_chernenko_squad") return squad_se and squad_se.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_3_task_3_status_f(tsk,task_id) if western_goods_utils.has_info("western_goods_act_3_task_3_init") then -- First stage : Find and kill/bribe supervisor if tsk.stage == 0 then local squad_se = western_goods_utils.server_object_by_sid("western_goods_ssu_supervisor_squad") if not squad_se and not TASK_3_CACHE.supervisor_spawned then squad_se = task_3_spawn_supervisor_squad() TASK_3_CACHE.supervisor_spawned = true return end if squad_se and not western_goods_utils.has_info("western_goods_ssu_supervisor_bribed") then return end if not TASK_3_CACHE.danylo_message_sent then local sender_1 = alife():actor() local sender_2 = western_goods_utils.server_object_by_sid("stalker_danylo_chernenko") if not squad_se then dbg_printf("[WG] Tasks Act 3 | Task 3 - Stage 0 - SSU supervisor is dead...") send_dialog({ {sender=sender_1:character_name(), icon=sender_1:character_icon(), message=western_goods_utils.get_translation("st_wg_act_3_task_3_stage_0_message_1")}, {sender=sender_2:character_name(), icon=sender_2:character_icon(), message=western_goods_utils.get_translation("st_wg_act_3_task_3_stage_0_message_2")}, }) elseif western_goods_utils.has_info("western_goods_ssu_supervisor_bribed") then dbg_printf("[WG] Tasks Act 3 | Task 3 - Stage 0 - SSU supervisor was bribed...") send_dialog({ {sender=sender_1:character_name(), icon=sender_1:character_icon(), message=western_goods_utils.get_translation("st_wg_act_3_task_3_stage_0_message_3")}, {sender=sender_2:character_name(), icon=sender_2:character_icon(), message=western_goods_utils.get_translation("st_wg_act_3_task_3_stage_0_message_4")}, }) end western_goods_utils.give_info("western_goods_danylo_army_warehouses") dbg_printf("[WG] Tasks Act 3 | Task 3 - Stage 0 - Teleported Danylo squad...") TASK_3_CACHE.danylo_message_sent = true end tsk.stage = 1 end -- First stage : Return to Danylo if tsk.stage == 1 then western_goods_utils.give_info("western_goods_act_3_task_3_ready_finished") end end end -- --------------------------------------------------------------------------------------------------------------------- -- TASK 4 - REUNION -- --------------------------------------------------------------------------------------------------------------------- --- Function used to start Act 3, Task 4. --- @param first_speaker cse_alife_object --- @param second_speaker cse_alife_object --- @return nil function act_3_task_4_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_3_task_4", npc:id()) dbg_printf("[WG] Tasks Act 3 | Task 4 - Task started...") end --- Function used to end Act 3, Task 4. --- @return nil function act_3_task_4_end() task_manager.get_task_manager():set_task_completed("western_goods_act_3_task_4") dbg_printf("[WG] Tasks Act 3 | Task 4 - 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_3_task_4_init(actor,npc) -- Process info portions western_goods_utils.give_info("western_goods_act_3_task_4_active") western_goods_utils.give_info("western_goods_act_3_task_4_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_3_task_4_complete(actor,npc) -- Process info portions western_goods_utils.rem_info("western_goods_act_3_task_4_active") western_goods_utils.rem_info("western_goods_act_3_task_4_init") western_goods_utils.give_info("western_goods_act_3_task_4_finished") western_goods_utils.give_info("western_goods_act_3_finished") -- Remove Danylo as companion local npc_se = western_goods_utils.server_object_by_sid("stalker_danylo_chernenko") local npc_obj = npc_se and western_goods_utils.level_object_by_id(npc_se.id) this.task_4_rem_danylo_companion(npc_obj) -- Process reward xr_effects.reward_random_money(actor,npc,{"50000","75000"}) xr_effects.reward_stash(actor,npc,{"true"}) xr_effects.complete_task_inc_goodwill(actor,npc,{"200","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_3_task_4_fail(actor,npc) -- Process info portions western_goods_utils.rem_info("western_goods_act_3_task_4_active") western_goods_utils.rem_info("western_goods_act_3_task_4_init") -- 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_3_task_4_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_3_task_4_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_3_task_4_stage__descr. --- @param task_id number --- @param field string --- @param p any --- @param tsk CGameTask --- @return string function task_functor.act_3_task_4_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_3_task_4_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_3_task_4_target_f(task_id,field,p,tsk) if western_goods_utils.has_info("western_goods_act_3_task_4_init") then if tsk.stage == 0 then local squad_se = western_goods_utils.server_object_by_sid("stalker_danylo_chernenko_squad") return squad_se and squad_se.id end if tsk.stage == 1 then local squad_se = western_goods_utils.server_object_by_sid("stalker_oleksandr_chernenko_squad") return squad_se and squad_se.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_3_task_4_status_f(tsk,task_id) if western_goods_utils.has_info("western_goods_act_3_task_4_init") then -- First stage : Get Danylo as companion if tsk.stage == 0 then local npc_se = western_goods_utils.server_object_by_sid("stalker_danylo_chernenko") local npc_obj = npc_se and western_goods_utils.level_object_by_id(npc_se.id) -- Fail task if Danylo is dead if not npc_se or not npc_se:alive() then return "fail" end -- Wait for object to be online if not npc_obj then return end -- Become companion this.task_4_add_danylo_companion(npc_obj) if dialogs_axr_companion.is_actor_companion(nil,npc_obj) then tsk.stage = 1 end end -- Second stage : Meet with Oleksandr if tsk.stage == 1 then local npc_se = western_goods_utils.server_object_by_sid("stalker_danylo_chernenko") local npc_obj = npc_se and western_goods_utils.level_object_by_id(npc_se.id) -- Fail task if Danylo is dead if not npc_se or not npc_se:alive() then return "fail" end -- Wait for object to be online if not npc_obj then western_goods_utils.rem_info("western_goods_act_3_task_4_ready_finished") return end western_goods_utils.give_info("western_goods_act_3_task_4_ready_finished") 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("on_specific_character_dialog_list", task_1_usb_unlock_dialog) 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 = {} local TASK_4_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) copy_table(TASK_4_SAVE, TASK_4_CACHE) -- Pre-process tables -- Save tables m_data.wg_act_3_task_1_cache = TASK_1_SAVE m_data.wg_act_3_task_2_cache = TASK_2_SAVE m_data.wg_act_3_task_3_cache = TASK_3_SAVE m_data.wg_act_3_task_4_cache = TASK_4_SAVE -- Debug prints dbg_printf("[WG] Tasks Act 3 | Task 1 - Saved variables...\n%s",utils_data.print_table(TASK_1_SAVE, false, true)) dbg_printf("[WG] Tasks Act 3 | Task 2 - Saved variables...\n%s",utils_data.print_table(TASK_2_SAVE, false, true)) dbg_printf("[WG] Tasks Act 3 | Task 3 - Saved variables...\n%s",utils_data.print_table(TASK_3_SAVE, false, true)) dbg_printf("[WG] Tasks Act 3 | Task 4 - Saved variables...\n%s",utils_data.print_table(TASK_4_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_3_task_1_cache or {} local TASK_2_SAVE = m_data.wg_act_3_task_2_cache or {} local TASK_3_SAVE = m_data.wg_act_3_task_3_cache or {} local TASK_4_SAVE = m_data.wg_act_3_task_4_cache or {} -- Post-process tables -- 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) copy_table(TASK_4_CACHE, TASK_4_SAVE) -- Debug prints dbg_printf("[WG] Tasks Act 3 | Task 1 - Loaded variables...\n%s",utils_data.print_table(TASK_1_CACHE, false, true)) dbg_printf("[WG] Tasks Act 3 | Task 2 - Loaded variables...\n%s",utils_data.print_table(TASK_2_CACHE, false, true)) dbg_printf("[WG] Tasks Act 3 | Task 3 - Loaded variables...\n%s",utils_data.print_table(TASK_3_CACHE, false, true)) dbg_printf("[WG] Tasks Act 3 | Task 4 - Loaded variables...\n%s",utils_data.print_table(TASK_4_CACHE, false, true)) end -- --------------------------------------------------------------------------------------------------------------------- -- General functions -- --------------------------------------------------------------------------------------------------------------------- --- Function used to give the player a reward for finishing act 1. --- @return cse_alife_object|nil function task_1_give_item(first_speaker, second_speaker) dialogs.relocate_item_section_to_actor(first_speaker, second_speaker, "wg_stash_map_quest_item") end --- Function used to get the server object of the stash in which to spawn Act 3, Task 1's primary quest item. --- @return cse_alife_object|nil function task_1_get_spawn_stash() local stash_se = nil western_goods_utils.server_objects_iter(function(se_obj) local obj_lid = se_obj and game_graph():vertex(se_obj.m_game_vertex_id):level_id() local obj_lname = obj_lid and obj_lid < 50 and alife():level_name(obj_lid) if obj_lname == "l03u_agr_underground" and se_obj:name() == "level_prefix_inventory_box_0001" then stash_se = se_obj dbg_printf("[WG] Tasks Act 3 | Task 1 - Found Agroprom's stash %s", stash_se.id) return true end end) return stash_se end --- Function used to add a task dialog to all technicians. --- @param character_id string --- @param dialog_list table --- @return nil function task_1_usb_unlock_dialog(character_id, dialog_list) if dialog_list:has("dm_init_mechanic") then local res = dialog_list:add(CONST_TASK_1_USB_UNLOCK_DIALOG_ID) if res then dbg_printf("[WG] Tasks Act 3 | Task 1 - Added dialog %s for %s, pos %s", CONST_TASK_1_USB_UNLOCK_DIALOG_ID, character_id, res) end end end --- Function used to determine if the task dialog should be shown or not. --- @return boolean function task_1_usb_unlock_dialog_cond() local cond_stage = xr_conditions.check_task_stage(nil,nil,{"western_goods_act_3_task_1","2"}) local cond_note = not ui_pda_encyclopedia_tab.is_unlocked_note("encyclopedia__notes_western_goods_hand_drawn_map") local cond_obj = db.actor:object("wg_danylo_pendrive_quest_item") return cond_stage and cond_obj and cond_note end --- Function used to determine if the player has enough money to use the task dialog line. --- @return boolean function task_1_usb_unlock_money_cond() return db.actor:money() >= CONST_TASK_1_USB_UNLOCK_COST end --- Function used to unlock the pda encyclopedia entry via a technician. --- @param actor game_object --- @param npc game_object --- @return nil function task_1_usb_unlock(npc, actor) western_goods_usable_items.use_danylo_pendrive() dialogs.relocate_money(npc, CONST_TASK_1_USB_UNLOCK_COST, "out") end --- Function used to progress the task once the player has finished the interrogation. --- @return nil function task_2_interrogation_over() local tsk = task_manager.get_task_manager().task_info["western_goods_act_3_task_2"] if (tsk and tsk.stage and tsk.stage == 0) then -- Spawn quest item (and squad) if not western_goods_utils.server_object_by_sid("wg_deployment_notice_quest_item") then local squad_se = task_2_spawn_bounty_squad() local document_se = task_2_spawn_quest_item(squad_se) end dbg_printf("[WG] Tasks Act 3 | Task 2 - Stage 0 - Player finished interrogation...") tsk.stage = 1 end end --- Function used to spawn the bounty squad for Act 3, Task 2. --- @return cse_alife_online_offline_group function task_2_spawn_bounty_squad() local squad_se = western_goods_utils.server_object_by_sid("western_goods_ssu_bounty_squad") if not squad_se then squad_se = western_goods_utils.spawn_squad_smart("western_goods_ssu_bounty_squad", "zat_b14_smart_terrain") squad_se.scripted_target = "zat_b14_smart_terrain" dbg_printf("[WG] Tasks Act 3 | Task 2 - Spawned SSU bounty squad with id %s", squad_se.id) end return squad_se end --- Function used to spawn the bounty squad for Act 3, Task 2. --- @param squad_se cse_alife_online_offline_group --- @return cse_alife_object function task_2_spawn_quest_item(squad_se) local document_se = western_goods_utils.server_object_by_sid("wg_deployment_notice_quest_item") if not document_se then local member_se = western_goods_utils.get_member_from_squad(squad_se) document_se = alife_create_item("wg_deployment_notice_quest_item", member_se) dbg_printf("[WG] Tasks Act 3 | Task 2 - Spawned document id %s inside member id %s of squad id %s", document_se.id, member_se.id, squad_se.id) end return document_se end --- Function called from dialog, used to reset the interrogation points counter. --- @return nil function task_2_init_interrogation() TASK_2_CACHE.interrogation_points = 0 end --- Function called from dialog, used to increment the interrogation points counter. --- @return nil function task_2_incr_interrogation() TASK_2_CACHE.interrogation_points = TASK_2_CACHE.interrogation_points + 10 end --- Function called from dialog, used to decrement the interrogation points counter. --- @return nil function task_2_normal_interrogation() TASK_2_CACHE.interrogation_points = TASK_2_CACHE.interrogation_points + 5 end --- Function called from dialog, used to decrement the interrogation points counter. --- @return nil function task_2_decr_interrogation() TASK_2_CACHE.interrogation_points = TASK_2_CACHE.interrogation_points - 15 end --- Function used to spawn the supervisor the player has to kill during Act 3, Task 2. --- @return cse_alife_online_offline_group function task_3_spawn_supervisor_squad() local squad_supervisor_se = western_goods_utils.server_object_by_sid("western_goods_ssu_supervisor_squad") if not squad_supervisor_se then -- Spawn supervisor squad squad_supervisor_se = western_goods_utils.spawn_squad_smart("western_goods_ssu_supervisor_squad", "mar_smart_terrain_10_5") -- Spawn supervisor guards local squad_guard_1_se = western_goods_utils.spawn_squad_smart("army_sim_squad_veteran", "mar_smart_terrain_10_5") local squad_guard_2_se = western_goods_utils.spawn_squad_smart("army_sim_squad_veteran", "mar_smart_terrain_10_5") -- Force to stay at 'mar_smart_terrain_10_5' squad_supervisor_se.scripted_target = "mar_smart_terrain_10_5" squad_guard_1_se.scripted_target = "mar_smart_terrain_10_5" squad_guard_2_se.scripted_target = "mar_smart_terrain_10_5" dbg_printf("[WG] Tasks Act 3 | Task 3 - Spawned SSU supervisor squad with id %s", squad_supervisor_se.id) end return squad_supervisor_se end --- Function used to get the scripted text for one of the bribe lines of dialog with the SSU supervisor. --- @return string function task_3_st_bribe_dialog() return western_goods_utils.get_translation("western_goods_ssu_supervisor_bribe_2", CONST_TASK_3_BRIBE_COST) end --- Function used to bribe the SSU supervisor and progress the task. --- @param actor game_object --- @param npc game_object --- @return nil function task_3_bribe(npc, actor) dialogs.relocate_money(npc, CONST_TASK_3_BRIBE_COST, "out") local tsk = task_manager.get_task_manager().task_info["western_goods_act_3_task_3"] if (tsk and tsk.stage and tsk.stage == 0) then dbg_printf("[WG] Tasks Act 3 | Task 3 - Stage 0 - SSU supervisor was bribed...") if not TASK_3_CACHE.danylo_message_sent then local sender_1 = alife():actor() local sender_2 = western_goods_utils.server_object_by_sid("stalker_danylo_chernenko") send_dialog({ {sender=sender_1:character_name(), icon=sender_1:character_icon(), message=western_goods_utils.get_translation("st_wg_act_3_task_3_stage_0_message_3")}, {sender=sender_2:character_name(), icon=sender_2:character_icon(), message=western_goods_utils.get_translation("st_wg_act_3_task_3_stage_0_message_4")}, }) western_goods_utils.give_info("western_goods_danylo_army_warehouses") dbg_printf("[WG] Tasks Act 3 | Task 3 - Stage 0 - Teleported Danylo squad...") TASK_3_CACHE.danylo_message_sent = true end tsk.stage = 1 end end --- Function used to determine if the player has enough money to access the bribe dialog with the SSU supervisor. --- @return boolean function task_3_bribe_dialog_cond() return db.actor:money() >= CONST_TASK_3_BRIBE_COST end --- Function used to add Danylo as a companion. --- @param danylo_obj game_object --- @return nil function task_4_add_danylo_companion(danylo_obj) if dialogs_axr_companion.is_not_actor_companion(nil,danylo_obj) then dialogs_axr_companion.become_actor_companion(db.actor,danylo_obj) end end --- Function used to remove Danylo as a companion. --- @param danylo_obj game_object --- @return nil function task_4_rem_danylo_companion(danylo_obj) if dialogs_axr_companion.is_actor_companion(nil,danylo_obj) then axr_companions.remove_from_actor_squad(danylo_obj) end end