sr2lua/ss08.lua

  1. -- ss08.lua 
  2. -- SR2 mission script 
  3. -- 3/28/07 
  4. -- Mission help table text tags 
  5.    HT_TRUCK_DESTROYED = "ss08_truck_destroyed" 
  6.    HT_GET_BACK_TO_WAREHOUSE = "ss08_get_back_to_warehouse" 
  7.    HT_WAREHOUSE_ABANDONED = "ss08_warehouse_abandoned" 
  8.    HT_DEFEND_THE_DUST = "ss08_defend_the_dust" 
  9.    HT_PIERCE_DIED = "ss08_pierce_died" 
  10.    HT_SHAUNDI_DIED = "ss08_shaundi_died" 
  11.    HT_PIERCE_ABANDONED = "ss08_pierce_abandoned" 
  12.    HT_SHAUNDI_ABANDONED = "ss08_shaundi_abandoned" 
  13.    HT_PROTECT_WHILE_LOADING = "ss08_protect_while_loading" 
  14.    HT_GET_DRUGS_TO_HQ = "ss08_get_drugs_to_hq" 
  15.    HT_PIERCE_WAITING_ON_YOU = "ss08_pierce_waiting_on_you" 
  16.    HT_GET_A_CAR = "ss08_get_a_car" 
  17.    HT_ESCORT_TRUCK_TO_HIDEOUT = "ss08_escort_truck_to_hideout" 
  18.    HT_TRUCK_HEALTH = "ss08_truck_health" 
  19.    HT_X_OF_Y_BOXES_LOADED = "ss08_x_of_y_crates_loaded" 
  20.  
  21. -- Mission states 
  22.    MS_INIT = 1 
  23.    MS_INITIAL_JUNKIES_ATTACK = 2 
  24.    MS_REAL_ATTACK_STARTS = 3 
  25.    MS_WAITING_FOR_PIERCE = 4 
  26.    MS_LOADING_TRUCK = 5 
  27.    MS_TRUCK_LOADED = 6 
  28.    MS_TRAVELING_TO_BASE = 7 
  29.    MS_VICTORY = 8 
  30.  
  31. -- Groups, NPCs, vehicles, navpoints, and other names 
  32.    -- Mission constant names 
  33.    MISSION_NAME = "ss08" 
  34.    -- ( Mission Prefix ) 
  35.    MP = MISSION_NAME.."_$" 
  36.  
  37.    CHASE_GROUP_GROUP_PREFIX = MP.."Chase_Group" 
  38.    CHASE_GROUP_OBJECT_PREFIX = MP.."CG_" 
  39.    CHASE_GROUP_NPC_SUFFIX = "_M" 
  40.    CHASE_GROUP_VEHICLE_SUFFIX = "_V" 
  41.    CHASE_GROUP_TRIGGER_SUFFIX = "_T" 
  42.  
  43.    WEST = 1 
  44.    EAST = 2 
  45.    SOUTH = 3 
  46.  
  47.    POLICE_GANG = "police" 
  48.  
  49.    -- Checkpoints 
  50.    CP_TRUCK_LOADED = "Truck_Loaded" 
  51.  
  52.    -- Loading states - for loading packages 
  53.    LS_NONE = 0 
  54.    LS_CARRYING_TO_DROPOFF = 1 
  55.    LS_MOVING_TO_PICK_UP = 2 
  56.    LS_WAITING_AT_DROPOFF = 3 
  57.    LS_WAITING_AT_PICKUP = 4 
  58.    LS_DISABLED = 5 
  59.    LS_JUST_REVIVED = 6 
  60.  
  61.    -- Groups 
  62.    HOMIES_GROUP = MP.."Saint_Homies" 
  63.    DRUG_TRUCK_LOADING_GROUP = MP.."Drug_Truck_Loading" 
  64.    DRUG_TRUCK_GROUP = MP.."Drug_Truck" 
  65.    JUNKIES_GROUP = MP.."Initial_Attack_Junkies" 
  66.    ESCAPE_CAR_GROUP = MP.."Escape_Car" 
  67.    CUTSCENE_GROUP = MP.."Cutscene" 
  68.    OUTSIDE_OF_WAREHOUSE_AMBUSHER_GROUP = MP.."Outside_of_Warehouse_Ambush" 
  69.    PATH_AMBUSHER_GROUPS = { MP.."Path_Ambush_01", MP.."Path_Ambush_02" } 
  70.  
  71.    ALL_ATTACK_SQUADS = { [WEST] = MP.."West_01", [EAST] = MP.."East_01", [SOUTH] = MP.."South_01" } 
  72.  
  73.    CHASE_SQUAD_GROUP_NAMES = {} 
  74.  
  75.    DRUG_BOXES_GROUP = MP.."Drug_Boxes" 
  76.  
  77.    RANDOM_CHASE_SQUAD_GROUPS = { MP.."Random_Chase_Squad1", MP.."Random_Chase_Squad2", MP.."Random_Chase_Squad3" } 
  78.  
  79.    -- NPC names 
  80.    INITIAL_ATTACK_JUNKIE_NAMES = { MP.."Initial_Junkie01", MP.."Initial_Junkie02", MP.."Initial_Junkie03", 
  81.                                    MP.."Initial_Junkie04", MP.."Initial_Junkie05", MP.."Initial_Junkie06" } 
  82.    PIERCE_NAME = MP.."Pierce" 
  83.    SHAUNDI_NAME = MP.."Shaundi" 
  84.    WEST_ATTACK_SQUAD_MEMBERS = { MP.."West_01_M01", MP.."West_01_M02", MP.."West_01_M03" } 
  85.    EAST_ATTACK_SQUAD_MEMBERS = { MP.."East_01_M01", MP.."East_01_M02", MP.."East_01_M03" } 
  86.    SOUTH_ATTACK_SQUAD_MEMBERS = { MP.."South_01_M01", MP.."South_01_M02", MP.."South_01_M03" } 
  87.  
  88.    ATTACK_SQUADS_MEMBERS = { [WEST] = WEST_ATTACK_SQUAD_MEMBERS, [EAST] = EAST_ATTACK_SQUAD_MEMBERS, 
  89.                              [SOUTH] = SOUTH_ATTACK_SQUAD_MEMBERS } 
  90.  
  91.    OUTSIDE_OF_WAREHOUSE_AMBUSHER_MEMBERS = { MP.."Ambusher_01", MP.."Ambusher_02", MP.."Ambusher_03" } 
  92.  
  93.    PATH_AMBUSHER_GROUPS_MEMBERS = { { MP.."PA1_M01", MP.."PA1_M02", MP.."PA1_M03" }, 
  94.                                     { MP.."PA2_M01", MP.."PA2_M02", MP.."PA2_M03" } } 
  95.  
  96.    RANDOM_CHASE_SQUAD_MEMBERS = { { MP.."RC1_M1", MP.."RC1_M2" }, 
  97.                                   { MP.."RC2_M1", MP.."RC2_M2" }, 
  98.                                   { MP.."RC3_M1", MP.."RC3_M2", MP.."RC3_M3", MP.."RC3_M4" } } 
  99.  
  100.    CHASE_SQUAD_GROUP_MEMBERS = {} 
  101.  
  102.    -- Vehicle names 
  103.    DRUG_TRUCK_LOADING = MP.."Drug_Truck_02" 
  104.    DRUG_TRUCK = MP.."Drug_Truck" 
  105.  
  106.    ATTACK_SQUAD_VEHICLES = { [EAST] =  MP.."East_V1", [WEST] = MP.."West_V1", 
  107.                              [SOUTH] = MP.."South_V1" } 
  108.  
  109.    ESCAPE_CAR_NAME = MP.."Escape_Car" 
  110.  
  111.    RANDOM_CHASE_SQUAD_VEHICLES = { MP.."RC1_V", MP.."RC2_V", MP.."RC3_V" } 
  112.  
  113.    CHASE_SQUAD_GROUP_VEHICLES = {} 
  114.  
  115.    -- Navpoints 
  116.    PLAYER1_START = MP.."Player1_Start" 
  117.    PLAYER2_START = MP.."Player2_Start" 
  118.    BOX_PICKUP_NAV = MP.."Box_Pickup_Position" 
  119.    BOX_DROPOFFS = { [PIERCE_NAME] = MP.."Pierce_Dropoff", [SHAUNDI_NAME] = MP.."Shaundi_Dropoff" } 
  120.  
  121.    BOX_LOADING_TARGET = MP.."Box_Loading_Target" 
  122.  
  123.    PIERCE_GET_TRUCK_PATH = { MP.."PE_00", MP.."PE_01", MP.."PE_02", MP.."PE_03", 
  124.                              MP.."PE_04", MP.."PE_05", MP.."PE_06", MP.."PE_07", 
  125.                              MP.."PE_08", MP.."PE_09", MP.."PE_10", MP.."PE_11" } 
  126.    PIERCE_RETURN_TO_LOAD_TRUCK_PATH = { MP.."PR_01", MP.."PR_02", MP.."PR_03", 
  127.                                         MP.."PR_04", MP.."PR_05" } 
  128.  
  129.    ATTACK_VEHICLE_PATHS = { [EAST] = MP.."Attack_Path_East", [WEST] = MP.."Attack_Path_West", 
  130.                             [SOUTH] = MP.."Attack_Path_South" } 
  131.  
  132.    BACK_TO_HQ_PATH_INITIAL = MP.."THQ_Initial_Path" 
  133.    BACK_TO_HQ_PATHS_MAIN = { MP.."THQ_01", MP.."THQ_02" } 
  134.  
  135.    BACK_TO_HQ_PATH_FINAL = MP.."THQ_Final_Path" 
  136.  
  137.    DROPOFF_POINTS = { [EAST] = { MP.."Dropoff_E01", MP.."Dropoff_E02", MP.."Dropoff_E03", MP.."Dropoff_E04", MP.."Dropoff_E05" }, 
  138.                       [WEST] = { MP.."Dropoff_W01", MP.."Dropoff_W02", MP.."Dropoff_W03", MP.."Dropoff_W04", MP.."Dropoff_W05" }, 
  139.                       [SOUTH] = { MP.."Dropoff_S01", MP.."Dropoff_S02", MP.."Dropoff_S03", MP.."Dropoff_S04" } } 
  140.  
  141.    AMBUSHER_GOALS = { MP.."Ambusher01_Goal", MP.."Ambusher02_Goal", MP.."Ambusher03_Goal" } 
  142.  
  143.    RANDOM_CHASE_SQUAD_SPAWN_LOCATIONS = { MP.."Path_Spawn01", MP.."Path_Spawn02", MP.."Path_Spawn03", MP.."Path_Spawn04", 
  144.                                           MP.."Path_Spawn05", MP.."Path_Spawn06", MP.."Path_Spawn07", MP.."Path_Spawn08", 
  145.                                           MP.."Path_Spawn09", MP.."Path_Spawn10", MP.."Path_Spawn11", MP.."Path_Spawn12", 
  146.                                           MP.."Path_Spawn13", MP.."Path_Spawn14", MP.."Path_Spawn15", MP.."Path_Spawn16", 
  147.                                           MP.."Path_Spawn17" } 
  148.  
  149.    ARRIVAL_NAVPOINTS = { [LOCAL_PLAYER] = MP.."P1_Arrival", [REMOTE_PLAYER] = MP.."P2_Arrival" } 
  150.  
  151.    -- Triggers 
  152.    WAREHOUSE_AREA = MP.."Warehouse_Area" 
  153.  
  154.    SAINTS_HQ = MP.."Saints_HQ" 
  155.  
  156.    CHASE_SQUAD_TRIGGER_NAMES = {} 
  157.    OUTSIDE_OF_WAREHOUSE_AMBUSH_TRIGGER = MP.."Outside_of_Warehouse_Ambush" 
  158.    PATH_AMBUSHER_TRIGGERS = { MP.."Path_Ambush_01_Trigger", MP.."Path_Ambush_02_Trigger" } 
  159.  
  160.    -- Movers 
  161.    DRUG_BOXES = { MP.."Drug_Box_01", MP.."Drug_Box_02", MP.."Drug_Box_03", MP.."Drug_Box_04", MP.."Drug_Box_05", 
  162.                   MP.."Drug_Box_06", MP.."Drug_Box_07", MP.."Drug_Box_08", MP.."Drug_Box_09", MP.."Drug_Box_10", 
  163.                   MP.."Drug_Box_11", MP.."Drug_Box_12" } 
  164.    GARAGE_DOOR = MP.."Garage_Door" 
  165.    DOORS = { MP.."Door01", MP.."Door02", MP.."Door03" } 
  166.  
  167.    -- Effects and animation states 
  168.  
  169.    -- Weapons 
  170.    CHASE_SQUAD_HEAVY_WEAPONS = { "twelve_gauge", "gal43" } 
  171.    CHASE_SQUAD_THROWN_WEAPONS = { "molotov" } 
  172.    CHASE_SQUAD_LIGHT_WEAPONS = { "beretta" } 
  173.     
  174.    -- Cutscenes 
  175.    ARRIVAL_CUTSCENE_NAME = "ig_ss08_scene0" 
  176.    SEATING_CUTSCENE_NAME = "ig_ss08_scene1" 
  177.    CT_INTRO = "ss08-01" 
  178.    CT_OUTRO = "ss08-02" 
  179. -- Sound 
  180.    -- Persona overrides 
  181.    SHAUNDI_JUNKIE_COMBAT_PERSONA_OVERRIDES = { { "combat - congratulate self", "SHAUNDI_SOS8_CONGRAT" }, 
  182.                                                { "threat - damage received (firearm)", "SHAUNDI_SOS8_TAKEDAM" }, 
  183.                                                { "threat - damage received (melee)", "SHAUNDI_SOS8_TAKEDAM" } } 
  184.  
  185.    -- Lines/Dialog Stream 
  186.    PIERCE_COMPLAINING_DIALOG_STREAM = { { "SOS8_GRIPE_L1", PIERCE_NAME } } 
  187.    PLAYER_RESPONSE_TO_GRIPE_DIALOG_STREAM = { { "PLAYER_SOS8_GRIPE_L2", LOCAL_PLAYER } } 
  188.  
  189.    GET_THE_TRUCK_DIALOG_STREAM = { { "SOS8_TRUCK_L1", SHAUNDI_NAME, 0 }, 
  190.                                    { "PLAYER_SOS8_TRUCK_L2", LOCAL_PLAYER, 0 }, 
  191.                                    { "SOS8_TRUCK_L3", PIERCE_NAME, 0 } } 
  192.  
  193.    PIERCE_RETURNS_DIALOG_STREAM = { { "SOS8_RETURN_L1", PIERCE_NAME }, 
  194.                                     { "PLAYER_SOS8_RETURN_L2", LOCAL_PLAYER } } 
  195.  
  196.    SHAUNDI_AND_PIERCE_ARGUE_DIALOG_STREAM = { { "SOS8_BICKER_L1", SHAUNDI_NAME }, 
  197.                                               { "SOS8_BICKER_L2", PIERCE_NAME }, 
  198.                                               { "SOS8_BICKER_L3", SHAUNDI_NAME }, 
  199.                                               { "SOS8_BICKER_L4", PIERCE_NAME }, 
  200.                                               { "SOS8_BICKER_L5", SHAUNDI_NAME }, 
  201.                                               { "SOS8_BICKER_L6", PIERCE_NAME }, 
  202.                                               { "SOS8_BICKER_L7", SHAUNDI_NAME }, 
  203.                                               { "SOS8_BICKER_L8", PIERCE_NAME } } 
  204.  
  205.    TRUCK_LOADED_DIALOG_STREAM = { { "SOS8_COMPLETE_L1", PIERCE_NAME }, 
  206.                                   { "PLAYER_SOS8_COMPLETE_L2", LOCAL_PLAYER } } 
  207.  
  208.    END_MISSION_DIALOG_STREAM = { { "SOS8_END_L1", PIERCE_NAME }, 
  209.                                  { "SOS8_END_L2", SHAUNDI_NAME }, 
  210.                                  { "SOS8_END_L3", PIERCE_NAME } } 
  211.  
  212.    SHAUNDI_DEFENDING_LINES = "SHAUNDI_SOS8_DEFEND" 
  213.    SHAUNDI_WHATS_TAKING_SO_LONG_LINE = "SHAUNDI_SOS8_TRUCK_02" 
  214.  
  215.    -- Sound effects 
  216.  
  217. -- Distances 
  218.    WAREHOUSE_AREA_TRIGGER_RADIUS_METERS = 34.8 
  219.    DRUG_TRUCK_MAX_DISTANCE_METERS = 50.0 
  220.    TO_HQ_WIN_DISTANCE_METERS = 10 
  221.  
  222. -- Percents and multipliers 
  223.  
  224. -- Time values 
  225.    FAILURE_TIME_MS = 30000 
  226.  
  227.    TIME_PER_ABANDONED_UPDATE_SECONDS = 5 
  228.  
  229.    BEFORE_ATTACK_DELAY_SECONDS = 6.0 
  230.    BEFORE_DEFEND_PROMPT_SECONDS = 3.5 
  231.  
  232.    WAIT_FOR_PIERCE_TIME_MS = 120000 
  233.    WHERE_IS_PIERCE_MESSAGE_DELAY_SECONDS = 60.0 
  234.    NEW_ENTRANCE_ATTACK_DELAY_SECONDS = 30.0 
  235.    -- The delay before spawning a new wave if the attackers 
  236.    -- during the siege falls below a certain number. 
  237.    BELOW_MIN_ATTACKERS_FORCE_SPAWN_DELAY_SECONDS = 10.0 
  238.    OUT_OF_RANGE_OF_TRUCK_FAIL_TIME_MS = 30000 
  239.    MIN_BETWEEN_LINES_DELAY_SECONDS = 8 
  240.    MAX_BETWEEN_LINES_DELAY_SECONDS = 16 
  241.    BEFORE_LOAD_PACKAGES_CONVERSATION_TIME_SECONDS = 15 
  242.    RANDOM_CHASE_SQUAD_SPAWN_INTERVAL_SECONDS = 15.0 
  243.  
  244. -- Speeds 
  245.    DRUG_TRUCK_INITIAL_SPEED_MPH = 20 
  246.    DRUG_TRUCK_DESIRED_SPEED_MPH = 30 
  247.  
  248. -- Constant values and counts 
  249.    -- The minimum number of attackers allowed during the siege. 
  250.    -- If the attackers fall below this number, a timer is 
  251.    -- started for a new attack wave. 
  252.    MIN_ATTACKERS = 3 
  253.    NUM_ATTACK_DIRECTIONS = 3 
  254.    NUM_DRUG_BOXES = sizeof_table( DRUG_BOXES ) 
  255.    INITIAL_DRUG_TRUCK_HP = 48000 
  256.  
  257.    CHASE_SQUAD_MEMBER_COUNTS = { 2, 2, 2, 2, 2, 2, 2, 2, 
  258.                                  2, 2, 2, 2, 2, 2, 2 } 
  259.    NUM_CHASE_SQUADS = sizeof_table( CHASE_SQUAD_MEMBER_COUNTS ) 
  260.    MAX_CHASING_CARS = 2 
  261.  
  262.    WAVES_BEFORE_DUAL_ATTACK = 2 
  263.  
  264.    FAILURE_TIME_INDEX = 0 
  265.    OBJECTIVE_TIME_INDEX = 1 
  266.  
  267.    RANDOM_CHASE_SQUAD_COUNT = sizeof_table( RANDOM_CHASE_SQUAD_GROUPS ) 
  268.  
  269.    -- The number of dropoffs available in each direction 
  270.    DROPOFF_COUNTS = { [WEST] = sizeof_table( DROPOFF_POINTS[WEST] ), 
  271.                       [EAST] = sizeof_table( DROPOFF_POINTS[EAST] ), 
  272.                       [SOUTH] = sizeof_table( DROPOFF_POINTS[SOUTH] ) } 
  273.  
  274. -- Global variables 
  275.    Initial_junkies_remaining = sizeof_table( INITIAL_ATTACK_JUNKIE_NAMES ) 
  276.    Players_in_warehouse_area = { [LOCAL_PLAYER] = true, [REMOTE_PLAYER] = true } 
  277.    Abandoned_warehouse_failure_threads = { [LOCAL_PLAYER] = INVALID_THREAD_HANDLE, [REMOTE_PLAYER] = INVALID_THREAD_HANDLE } 
  278.  
  279.    Cur_attack_directions = {} 
  280.    Cur_attackers_remaining = 0 
  281.    Cur_drug_boxes_remaining = NUM_DRUG_BOXES 
  282.  
  283.    Homie_drug_carry_states = { [PIERCE_NAME] = LS_NONE, [SHAUNDI_NAME] = LS_NONE } 
  284.    Homie_drug_carry_threads = { [PIERCE_NAME] = INVALID_THREAD_HANDLE, [SHAUNDI_NAME] = INVALID_THREAD_HANDLE } 
  285.  
  286.    Player_failure_countdown_threads = { [LOCAL_PLAYER] = INVALID_THREAD_HANDLE, [REMOTE_PLAYER] = INVALID_THREAD_HANDLE } 
  287.    Assault_turned_on = false 
  288.    Pierce_leaves_thread_handle = INVALID_THREAD_HANDLE 
  289.    Chase_squad_cars_chasing = {} 
  290.    Force_spawn_thread_handle = INVALID_THREAD_HANDLE 
  291.    Force_spawn_wave_index = 0 
  292.  
  293.    Num_junkie_attack_waves_defeated = 0 
  294.  
  295.    Num_chasing_cars = 0 
  296.    Last_random_chase_group_index = 0 
  297.  
  298.    Players_in_range_of_drug_truck = { [LOCAL_PLAYER] = false, [REMOTE_PLAYER] = false } 
  299.    Players_in_vehicle = { [LOCAL_PLAYER] = false, [REMOTE_PLAYER] = false } 
  300.    Followers_incapacitated = { [PIERCE_NAME] = false, [SHAUNDI_NAME] = false } 
  301.    Garage_door_open = false 
  302.    Whos_carrying_drug_boxes = { [DRUG_BOXES[1]] = nil, [DRUG_BOXES[2]] = nil, [DRUG_BOXES[3]] = nil, 
  303.                                 [DRUG_BOXES[4]] = nil, [DRUG_BOXES[5]] = nil, [DRUG_BOXES[6]] = nil, 
  304.                                 [DRUG_BOXES[7]] = nil, [DRUG_BOXES[8]] = nil, [DRUG_BOXES[9]] = nil, 
  305.                                 [DRUG_BOXES[10]] = nil, [DRUG_BOXES[11]] = nil, [DRUG_BOXES[12]] = nil } 
  306.  
  307.  
  308.    -- Index into DROPOFF_POINTS - the last dropoff index that was used 
  309.    -- from each direction. Initial value of zero denotes no dropoffs yet used 
  310.    Last_dropoff_indices = { [WEST] = 0, [EAST] = 0, [SOUTH] = 0 } 
  311.    Mission_won = false 
  312.    Drug_boxes_queued = 0 
  313.    Drug_boxes_loaded = 0 
  314.    Truck_waiting = false 
  315.    Group_spawning = false 
  316. 	Pierce_has_returned = false 
  317.    Argue_converstation_thread_handle = INVALID_THREAD_HANDLE 
  318.  
  319. function ss08_mission_critical_follower_dismissed( follower_name ) 
  320.    if ( follower_name == PIERCE_NAME ) then 
  321.       mission_end_failure( MISSION_NAME, HT_PIERCE_ABANDONED ) 
  322.    elseif ( follower_name == SHAUNDI_NAME ) then 
  323.       mission_end_failure( MISSION_NAME, HT_SHAUNDI_ABANDONED ) 
  324.    end 
  325. end 
  326.  
  327. function ss08_mission_critical_homie_died( homie_name ) 
  328.    if ( homie_name == PIERCE_NAME ) then 
  329.       mission_end_failure( MISSION_NAME, HT_PIERCE_DIED ) 
  330.    elseif ( homie_name == SHAUNDI_NAME ) then 
  331.       mission_end_failure( MISSION_NAME, HT_SHAUNDI_DIED ) 
  332.    end 
  333. end 
  334.  
  335. function ss08_all_players( player_conditions ) 
  336.    if ( player_conditions[LOCAL_PLAYER] ) then 
  337.       if ( coop_is_active() ) then 
  338.          if ( player_conditions[REMOTE_PLAYER] ) then 
  339.             return true 
  340.          end 
  341.       else 
  342.          return true 
  343.       end 
  344.    end 
  345.    return false 
  346. end 
  347.  
  348. function ss08_all_players_not( player_conditions ) 
  349.    if ( player_conditions[LOCAL_PLAYER] == false ) then 
  350.       if ( coop_is_active() ) then 
  351.          if ( player_conditions[REMOTE_PLAYER] == false ) then 
  352.             return true 
  353.          end 
  354.       else 
  355.          return true 
  356.       end 
  357.    end 
  358.    return false 
  359. end 
  360.  
  361. -- Returns true if all active players are out of range of the  
  362. -- drug truck, false otherwise. 
  363. -- 
  364. function ss08_all_players_out_of_range_of_truck() 
  365.    return ss08_all_players_not( Players_in_range_of_drug_truck ) 
  366. end 
  367.  
  368. function ss08_all_players_in_of_range_of_truck() 
  369.    return ss08_all_players( Players_in_range_of_drug_truck ) 
  370. end 
  371.  
  372. function ss08_all_players_in_vehicle() 
  373.    return ss08_all_players( Players_in_vehicle ) 
  374. end 
  375.  
  376. function ss08_all_players_in_warehouse_area() 
  377.    return ss08_all_players( Players_in_warehouse_area ) 
  378. end 
  379.  
  380.  
  381. function ss08_all_players_outside_warehouse_area() 
  382.    return ss08_all_players_not( Players_in_warehouse_area ) 
  383. end 
  384.  
  385. -- Tracks incapacitation while the boxes are being loaded 
  386. -- so that the boxes won't be 'loaded' when one of the people 
  387. -- isn't loading them. 
  388. --  
  389. function ss08_follower_incapacitated( follower_name ) 
  390.    local drug_thread_handle = Homie_drug_carry_threads[follower_name] 
  391.    if ( drug_thread_handle ~= INVALID_THREAD_HANDLE ) then 
  392.       thread_kill( drug_thread_handle ) 
  393.       Homie_drug_carry_threads[follower_name] = INVALID_THREAD_HANDLE 
  394.    end 
  395.  
  396.    for drug_box, whos_carrying in pairs( Whos_carrying_drug_boxes ) do 
  397.       if ( whos_carrying == follower_name ) then 
  398.          Drug_boxes_queued = Drug_boxes_queued - 1 
  399.          Whos_carrying_drug_boxes[drug_box] = nil 
  400.          item_drop( drug_box, follower_name ) 
  401.          item_reset( drug_box ) 
  402.       end 
  403.    end 
  404. end 
  405.  
  406. -- If a follower is revived while the boxes are being loaded, 
  407. -- this function checks to see if both followers are not 
  408. -- incapacitated and if so, resumes the loading. 
  409. -- 
  410. function ss08_follower_revived( follower_name ) 
  411.    Homie_drug_carry_threads[follower_name] = thread_new( "ss08_homie_load_drugs", follower_name ) 
  412. end 
  413.  
  414. function ss08_shaundi_revived() 
  415. end 
  416.  
  417. function ss08_open_doors( open ) 
  418.    if ( open == nil ) then 
  419.       open = true 
  420.    end 
  421.  
  422.    if ( open ) then 
  423.       for index, name in pairs( DOORS ) do 
  424.          door_open( name ) 
  425.       end 
  426.    else 
  427.       for index, name in pairs( DOORS ) do 
  428.          door_close( name ) 
  429.       end 
  430.    end 
  431. end 
  432.  
  433. function ss08_hide_doors( hide ) 
  434.    if ( hide == nil ) then 
  435.       hide = true 
  436.    end 
  437.  
  438.    if ( hide ) then 
  439.       for index, name in pairs( DOORS ) do 
  440.          door_lock( name, true ) 
  441.          mesh_mover_hide( name ) 
  442.       end 
  443.    else 
  444.       for index, name in pairs( DOORS ) do 
  445.          door_lock( name, false ) 
  446.          mesh_mover_show( name ) 
  447.       end 
  448.    end 
  449. end 
  450.  
  451. -- Works for numbers 0-99. 
  452. function ss08_get_zero_prefixed( number ) 
  453.    local prefixed = nil 
  454.    if ( number < 10 ) then 
  455.       prefixed = "0"..number 
  456.    else 
  457.       prefixed = number 
  458.    end 
  459.  
  460.    return prefixed 
  461. end 
  462.  
  463. function ss08_generate_chase_squad_trigger_and_group_names() 
  464.    for i = 1, NUM_CHASE_SQUADS do 
  465.       local index = ss08_get_zero_prefixed( i ) 
  466.       CHASE_SQUAD_TRIGGER_NAMES[i] = CHASE_GROUP_OBJECT_PREFIX..index..CHASE_GROUP_TRIGGER_SUFFIX 
  467.       CHASE_SQUAD_GROUP_NAMES[i] = CHASE_GROUP_GROUP_PREFIX..index 
  468.    end 
  469. end 
  470.  
  471. function ss08_generate_chase_squad_vehicle_names() 
  472.    for i = 1, NUM_CHASE_SQUADS do 
  473.       local index = ss08_get_zero_prefixed( i ) 
  474.       CHASE_SQUAD_GROUP_VEHICLES[i] = CHASE_GROUP_OBJECT_PREFIX..index..CHASE_GROUP_VEHICLE_SUFFIX 
  475.    end 
  476. end 
  477.  
  478. function ss08_generate_chase_squad_group_member_names() 
  479.    -- Go through all the group member counts 
  480.    for group_index, member_count in pairs( CHASE_SQUAD_MEMBER_COUNTS ) do 
  481.       -- For each member in the group 
  482.       local group_members = {} 
  483.       local group_index_prefixed = ss08_get_zero_prefixed( group_index ) 
  484.       for member_index = 1, member_count do 
  485.          -- Construct its name 
  486.          local member_index_prefixed = ss08_get_zero_prefixed( member_index ) 
  487.          group_members[member_index] = CHASE_GROUP_OBJECT_PREFIX..group_index_prefixed..CHASE_GROUP_NPC_SUFFIX..member_index_prefixed 
  488.       end 
  489.  
  490.       -- Add this group's members to the overall list 
  491.       CHASE_SQUAD_GROUP_MEMBERS[group_index] = group_members 
  492.    end 
  493. end 
  494.  
  495. function ss08_entered_warehouse_area( triggerer_name, trigger_name ) 
  496.    Players_in_warehouse_area[triggerer_name] = true 
  497.    local sync_type = sync_from_player( triggerer_name ) 
  498.    minimap_icon_remove_navpoint( WAREHOUSE_AREA, sync_type ) 
  499.    ss08_stop_failure_countdown( triggerer_name ) 
  500. end 
  501.  
  502. function ss08_left_warehouse_area( triggerer_name, trigger_name ) 
  503.    Players_in_warehouse_area[triggerer_name] = false 
  504.    local sync_type = sync_from_player( triggerer_name ) 
  505.    minimap_icon_add_navpoint_radius( WAREHOUSE_AREA, MINIMAP_ICON_LOCATION, WAREHOUSE_AREA_TRIGGER_RADIUS_METERS, nil, sync_type ) 
  506.    ss08_start_failure_countdown( triggerer_name ) 
  507. end 
  508.  
  509. -- This function starts a failure countdown for the passed-in player. 
  510. -- 
  511. -- player_name: Name of the player to start failure countdown for. 
  512. -- 
  513. function ss08_start_failure_countdown( player_name ) 
  514.    local sync_type = sync_from_player( player_name ) 
  515.  
  516.    Abandoned_warehouse_failure_threads[player_name] = thread_new( "ss08_abandoned_warehouse_fail_timer", sync_type ) 
  517. end 
  518.  
  519. function ss08_abandoned_warehouse_fail_timer( sync_type ) 
  520.    local cur_time_left_seconds = FAILURE_TIME_MS / 1000 
  521.    mission_help_table_nag( HT_GET_BACK_TO_WAREHOUSE, cur_time_left_seconds, "", sync_type ) 
  522.    while ( cur_time_left_seconds > 0 ) do 
  523.       delay( TIME_PER_ABANDONED_UPDATE_SECONDS ) 
  524.       cur_time_left_seconds = cur_time_left_seconds - TIME_PER_ABANDONED_UPDATE_SECONDS 
  525.       mission_help_table_nag( HT_GET_BACK_TO_WAREHOUSE, cur_time_left_seconds, "", sync_type ) 
  526.    end 
  527.  
  528.    mission_end_failure( MISSION_NAME, HT_WAREHOUSE_ABANDONED ) 
  529. end 
  530.  
  531. -- This function stops the failure countdown if one is on. 
  532. -- 
  533. -- player_name: Name of the player to stop the failure timer of. 
  534. -- 
  535. function ss08_stop_failure_countdown( player_name ) 
  536.    if ( Abandoned_warehouse_failure_threads[player_name] ~= INVALID_THREAD_HANDLE ) then 
  537.       thread_kill( Abandoned_warehouse_failure_threads[player_name] ) 
  538.       Abandoned_warehouse_failure_threads[player_name] = INVALID_THREAD_HANDLE 
  539.    end 
  540. end 
  541.  
  542. function ss08_abandoned_drugs() 
  543.    mission_end_failure( MISSION_NAME, HT_WAREHOUSE_ABANDONED ) 
  544. end 
  545.  
  546. function ss08_create_start_and_checkpoint_shared_groups( blocking_load ) 
  547. 	if ( group_is_loaded( ESCAPE_CAR_GROUP ) == false ) then 
  548. 		group_create_hidden( ESCAPE_CAR_GROUP, blocking_load ) 
  549. 	end 
  550. 	group_create_hidden( OUTSIDE_OF_WAREHOUSE_AMBUSHER_GROUP, blocking_load ) 
  551. 	for index, group_name in pairs( PATH_AMBUSHER_GROUPS ) do 
  552. 		group_create_hidden( group_name, blocking_load ) 
  553. 	end 
  554. 	for index, name in pairs( RANDOM_CHASE_SQUAD_GROUPS ) do 
  555. 		group_create_hidden( name, blocking_load ) 
  556. 	end 
  557. end 
  558.  
  559. function ss08_start( checkpoint_name, is_restart ) 
  560.    -- Start trigger is hit...the activate button was hit 
  561.    set_mission_author("Mark G. & Brad Johnson") 
  562.  
  563.    party_allow_max_followers( true ) 
  564.  
  565.    mission_start_fade_out() 
  566.    if ( checkpoint_name == MISSION_START_CHECKPOINT ) then 
  567. 		-- Cutscene and blocking group creation 
  568. 		if (not is_restart) then 
  569. 			cutscene_play( CT_INTRO, { HOMIES_GROUP, JUNKIES_GROUP, DRUG_BOXES_GROUP }, { PLAYER1_START, PLAYER2_START }, false ) 
  570. 		else 
  571. 			teleport_coop(PLAYER1_START, PLAYER2_START) 
  572. 			group_create_hidden( HOMIES_GROUP, true ) 
  573. 			group_create_hidden( JUNKIES_GROUP, true ) 
  574. 			group_create_hidden( DRUG_BOXES_GROUP, true ) 
  575. 		end 
  576.  
  577. 		-- Show groups that should be visible at mission start checkpoint 
  578. 		group_show( HOMIES_GROUP ) 
  579. 		group_show( JUNKIES_GROUP ) 
  580. 		group_show( DRUG_BOXES_GROUP ) 
  581.  
  582. 		parking_spot_enable( "parking_spots_$parking_341 (1)", false ) 
  583. 		parking_spot_enable( "parking_spots_$parking_341 (0)", false ) 
  584.  
  585. 		-- Non-blocking group creation for mission start 
  586. 		ss08_create_start_and_checkpoint_shared_groups( false ) 
  587.    end 
  588.  
  589.    ss08_generate_chase_squad_trigger_and_group_names() 
  590.    ss08_generate_chase_squad_group_member_names() 
  591.    ss08_generate_chase_squad_vehicle_names() 
  592.    ss08_hide_doors() 
  593.  
  594.    local next_state = nil 
  595.    local dont_play_cutscene = false 
  596.  
  597.    -- Create the ambush groups 
  598.    if ( checkpoint_name == MISSION_START_CHECKPOINT ) then 
  599.       teleport_coop( PLAYER1_START, PLAYER2_START ) 
  600.       next_state = MS_INIT 
  601.    else --if ( checkpoint_name == CP_TRUCK_LOADED ) then 
  602. 		teleport_coop( ARRIVAL_NAVPOINTS[LOCAL_PLAYER], ARRIVAL_NAVPOINTS[REMOTE_PLAYER] ) 
  603.  
  604. 		-- Create these groups blocking, because we need them right after the checkpoint 
  605. 		-- blocking_load = true 
  606. 		ss08_create_start_and_checkpoint_shared_groups( true ) 
  607.  
  608. 		group_create( DRUG_TRUCK_GROUP, true ) 
  609.  
  610.       follower_make_independent( PIERCE_NAME, true ) 
  611.       follower_make_independent( SHAUNDI_NAME, true )		 
  612. 		teleport( SHAUNDI_NAME, MP.."Pre_Enter_Shaundi", true ) 
  613. 		teleport( PIERCE_NAME, MP.."Pre_Enter_Pierce", true ) 
  614.  
  615.       vehicle_enter_group_teleport( { PIERCE_NAME, SHAUNDI_NAME }, DRUG_TRUCK ) 
  616.       vehicle_suppress_npc_exit( DRUG_TRUCK, true ) 
  617.       set_unjackable_flag( DRUG_TRUCK, true ) 
  618.  
  619.       dont_play_cutscene = true 
  620.       next_state = MS_TRUCK_LOADED 
  621.    end 
  622.  
  623.    mission_start_fade_in() 
  624.  
  625. 	mission_debug( "switching to initial state from start function", 15 ) 
  626.    ss08_switch_state( next_state, dont_play_cutscene ) 
  627. end 
  628.  
  629. function ss08_argue_conversation() 
  630.    delay( BEFORE_LOAD_PACKAGES_CONVERSATION_TIME_SECONDS ) 
  631.    audio_play_conversation( SHAUNDI_AND_PIERCE_ARGUE_DIALOG_STREAM, NOT_CALL ) 
  632. end 
  633.  
  634. -- Switches to a new mission state. 
  635. -- 
  636. -- new_state: The state to switch to. 
  637. -- extra_data: Extra information on the state change. 
  638. --             For MS_TRUCK_LOADED, sets whether or not 
  639. --             to play the cutscene ( default yes. ) 
  640. -- 
  641. function ss08_switch_state( new_state, extra_data ) 
  642.    if ( new_state == MS_INIT ) then 
  643.       -- Spawn the junkies 
  644.       for index, name in INITIAL_ATTACK_JUNKIE_NAMES do 
  645. 	      on_death( "ss08_initial_junkie_died", name ) 
  646.       end 
  647.       on_death( "ss08_mission_critical_homie_died", PIERCE_NAME ) 
  648.       on_death( "ss08_mission_critical_homie_died", SHAUNDI_NAME ) 
  649.  
  650.       trigger_enable( WAREHOUSE_AREA, true ) 
  651.       on_trigger( "ss08_entered_warehouse_area", WAREHOUSE_AREA ) 
  652.       on_trigger_exit( "ss08_left_warehouse_area", WAREHOUSE_AREA ) 
  653.  
  654.       if ( coop_is_active() ) then 
  655.          party_add( SHAUNDI_NAME, REMOTE_PLAYER ) 
  656.       else 
  657.          party_add( SHAUNDI_NAME, LOCAL_PLAYER ) 
  658.       end 
  659.       party_add( PIERCE_NAME, LOCAL_PLAYER ) 
  660.       on_dismiss( "ss08_mission_critical_follower_dismissed", PIERCE_NAME ) 
  661.       on_dismiss( "ss08_mission_critical_follower_dismissed", SHAUNDI_NAME ) 
  662.       thread_new( "ss08_before_attack_delay" ) 
  663.    elseif ( new_state == MS_INITIAL_JUNKIES_ATTACK ) then 
  664.  
  665.       -- Have them come at the player 
  666.       -- Track their status so that we know when they all die 
  667.       for index, name in INITIAL_ATTACK_JUNKIE_NAMES do 
  668.          attack_closest_player( name ) 
  669.       end 
  670.  
  671.       delay( BEFORE_DEFEND_PROMPT_SECONDS ) 
  672.       audio_play_conversation( PLAYER_RESPONSE_TO_GRIPE_DIALOG_STREAM, NOT_CALL ) 
  673.       mission_help_table( HT_DEFEND_THE_DUST, "", "", SYNC_ALL ) 
  674.  
  675.    elseif( new_state == MS_REAL_ATTACK_STARTS ) then 
  676.       audio_play_conversation( GET_THE_TRUCK_DIALOG_STREAM, NOT_CALL ) 
  677.  
  678. 		-- Don't have Pierce run away until he's alive and well 
  679. 		repeat 
  680. 			thread_yield() 
  681. 		until( character_is_ragdolled( PIERCE_NAME ) == false and character_is_dead( PIERCE_NAME ) == false ) 
  682.  
  683. 		mission_debug( "Pierce is not ragdolled or dead." ) 
  684. 		-- Now make sure he can't be killed and have him run off 
  685. 		turn_invulnerable( PIERCE_NAME ) 
  686.       -- Have Pierce run away and then disappear when he gets far enough away 
  687.       Pierce_leaves_thread_handle = thread_new( "ss08_pierce_leaves" ) 
  688.       -- Start a timer for Pierce's return. 
  689.       hud_timer_set( OBJECTIVE_TIME_INDEX, WAIT_FOR_PIERCE_TIME_MS, "ss08_pierce_returns" ) 
  690.       -- Make the timer hidden 
  691.       hud_timer_hide( OBJECTIVE_TIME_INDEX, true ) 
  692.  
  693.       for index, override in pairs( SHAUNDI_JUNKIE_COMBAT_PERSONA_OVERRIDES ) do 
  694.          persona_override_character_start( SHAUNDI_NAME, override[1], override[2] ) 
  695.       end 
  696.  
  697.       -- Start the junkie attack 
  698.       ss08_start_junkie_attack() 
  699.    elseif ( new_state == MS_LOADING_TRUCK ) then 
  700.       -- This has to be set to allow box loading to work 
  701.       set_dont_drop_havok_weapons_on_idle( true ) 
  702.  
  703.       for index, override in pairs( SHAUNDI_JUNKIE_COMBAT_PERSONA_OVERRIDES ) do 
  704.          persona_override_character_stop( SHAUNDI_NAME, override[1] ) 
  705.       end 
  706.  
  707.       hud_timer_stop( OBJECTIVE_TIME_INDEX ) 
  708.       hud_timer_hide( OBJECTIVE_TIME_INDEX, false ) 
  709.  
  710.       if ( Pierce_leaves_thread_handle ~= INVALID_THREAD_HANDLE ) then 
  711.          thread_kill( Pierce_leaves_thread_handle ) 
  712.          Pierce_leaves_thread_handle = INVALID_THREAD_HANDLE 
  713.       end 
  714.       -- Get ready for the cutscene 
  715.       vehicle_mark_as_players( ESCAPE_CAR_NAME ) 
  716.       spawning_vehicles( false ) 
  717.       spawning_vehicles( true ) 
  718. 		spawning_pedestrians( false ) 
  719. 		spawning_pedestrians( true ) 
  720. 		trigger_enable(WAREHOUSE_AREA,false) 
  721. 		on_trigger( "", WAREHOUSE_AREA ) 
  722.       on_trigger_exit( "", WAREHOUSE_AREA ) 
  723. 		ss08_stop_failure_countdown( LOCAL_PLAYER ) 
  724. 		if coop_is_active() then 
  725. 			ss08_stop_failure_countdown( REMOTE_PLAYER ) 
  726. 		end 
  727.       cutscene_play( ARRIVAL_CUTSCENE_NAME, DRUG_TRUCK_LOADING_GROUP, { ARRIVAL_NAVPOINTS[LOCAL_PLAYER], ARRIVAL_NAVPOINTS[REMOTE_PLAYER] } ) 
  728.       -- Have every living junkie attack the player again, because the cutscene can stop them 
  729. 		ss08_all_living_junkies_attack() 
  730.  
  731. 		on_trigger( "ss08_entered_warehouse_area", WAREHOUSE_AREA ) 
  732.       on_trigger_exit( "ss08_left_warehouse_area", WAREHOUSE_AREA ) 
  733. 		trigger_enable(WAREHOUSE_AREA,true) 
  734.       group_hide("ss08_$Arrival_Cutscene") 
  735.       group_destroy("ss08_$Arrival_Cutscene") 
  736.  
  737.       mesh_mover_play_action( GARAGE_DOOR, "start1") 
  738.       Garage_door_open = true 
  739.        
  740.       -- Place the truck in the driveway with Pierce in the seat 
  741.       group_show( DRUG_TRUCK_LOADING_GROUP ) 
  742.       on_vehicle_destroyed( "ss08_drug_truck_destroyed", DRUG_TRUCK_LOADING ) 
  743. 		teleport( PIERCE_NAME, "ss08_$cutscene_truck_half2" ) 
  744.       character_show( PIERCE_NAME ) 
  745.       --vehicle_enter_teleport( PIERCE_NAME, DRUG_TRUCK_LOADING, 0, true ) 
  746. 		--teleport_vehicle( DRUG_TRUCK_LOADING, DRUG_TRUCK_LOADING ) 
  747.  
  748.       -- Have Pierce come out of the truck and into the main area 
  749.       --vehicle_exit( PIERCE_NAME ) 
  750.       party_add( PIERCE_NAME, LOCAL_PLAYER ) 
  751.       follower_make_independent( PIERCE_NAME, true ) 
  752.       set_unjackable_flag( DRUG_TRUCK_LOADING, true ) 
  753.       vehicle_prevent_explosion_fling( DRUG_TRUCK_LOADING, true ) 
  754.       vehicle_infinite_mass( DRUG_TRUCK_LOADING, true ) 
  755.  
  756.       local run = 2 
  757.       local retry_on_failure = true 
  758.       local move_and_fire = false 
  759.       move_to( PIERCE_NAME, PIERCE_RETURN_TO_LOAD_TRUCK_PATH, run, retry_on_failure, move_and_fire ) 
  760.  
  761.       audio_play_conversation( PIERCE_RETURNS_DIALOG_STREAM, NOT_CALL ) 
  762.       mission_help_table( HT_PROTECT_WHILE_LOADING, "", "", SYNC_ALL ) 
  763.  
  764.       -- Once he's there, set him up to be the player's follower and start the loading sequence 
  765.       set_ignore_ai_flag( PIERCE_NAME, false ) 
  766.       turn_vulnerable( PIERCE_NAME ) 
  767.       on_dismiss( "ss08_mission_critical_follower_dismissed", PIERCE_NAME ) 
  768.  
  769.       -- Load up the drugs 
  770.       set_ignore_ai_flag( SHAUNDI_NAME, true ) 
  771.       set_ignore_ai_flag( PIERCE_NAME, true ) 
  772.       local walk = 1 
  773.       follower_make_independent( SHAUNDI_NAME, true ) 
  774. 		-- Have Shaundi get off a vehicle so that she doesn't get stuck on after she's  
  775. 		-- made independent 
  776. 		vehicle_exit( SHAUNDI_NAME ) 
  777.       on_incapacitated( "ss08_follower_incapacitated", PIERCE_NAME ) 
  778.       on_incapacitated( "ss08_follower_incapacitated", SHAUNDI_NAME ) 
  779.       on_revived( "ss08_follower_revived", PIERCE_NAME ) 
  780.       on_revived( "ss08_follower_revived", SHAUNDI_NAME ) 
  781.       objective_text( 0, HT_X_OF_Y_BOXES_LOADED, 0, NUM_DRUG_BOXES ) 
  782.       Homie_drug_carry_threads[PIERCE_NAME] = thread_new( "ss08_homie_load_drugs", PIERCE_NAME ) 
  783.       Homie_drug_carry_threads[SHAUNDI_NAME] = thread_new( "ss08_homie_load_drugs", SHAUNDI_NAME ) 
  784.       Argue_converstation_thread_handle = thread_new( "ss08_argue_conversation" ) 
  785.  
  786.    elseif ( new_state == MS_TRUCK_LOADED ) then 
  787.       if ( Argue_converstation_thread_handle ~= INVALID_THREAD_HANDLE and 
  788.            thread_check_done( Argue_converstation_thread_handle ) == false ) then 
  789.          thread_kill( Argue_converstation_thread_handle ) 
  790.       end 
  791.       Argue_converstation_thread_handle = INVALID_THREAD_HANDLE 
  792.  
  793.       on_incapacitated( "", PIERCE_NAME ) 
  794.       on_incapacitated( "", SHAUNDI_NAME ) 
  795.  
  796.       on_revived( "", PIERCE_NAME ) 
  797.       on_revived( "", SHAUNDI_NAME ) 
  798.  
  799.       mission_debug( "Entered 'truck loaded' state.", 15 ) 
  800.  
  801.       -- Reset the "don't drop weapons on idle" flag because the boxes are done loading 
  802.       set_dont_drop_havok_weapons_on_idle( false ) 
  803.  
  804.       -- Wait until everyone is alive before stopping the attack and such 
  805.       repeat 
  806.          thread_yield() 
  807.       until ( ss08_homies_alive() ) 
  808.  
  809.       notoriety_force_no_spawn( POLICE_GANG, true ) 
  810.       mission_debug( "Pierce and Shaundi alive. Spawning disabled...", 15 ) 
  811.  
  812.       -- Disable the in/out-of-warehouse tracking 
  813.       ss08_stop_failure_countdown( LOCAL_PLAYER ) 
  814.       if ( coop_is_active() ) then 
  815.          ss08_stop_failure_countdown( REMOTE_PLAYER ) 
  816.       end 
  817.       trigger_enable( WAREHOUSE_AREA, false ) 
  818.       minimap_icon_remove_navpoint( WAREHOUSE_AREA ) 
  819.       -- Turn off the assault 
  820.       Assault_turned_on = false 
  821.  
  822.       -- Show the ambush groups 
  823.       group_show( OUTSIDE_OF_WAREHOUSE_AMBUSHER_GROUP ) 
  824.       for index, group_name in pairs( PATH_AMBUSHER_GROUPS ) do 
  825.          group_show( group_name ) 
  826.       end 
  827.       -- Setup the triggers for the path ambush groups 
  828.       for index, trigger_name in pairs( PATH_AMBUSHER_TRIGGERS ) do 
  829.          trigger_enable( trigger_name, true ) 
  830.          on_trigger( "ss08_path_ambush_0"..index, trigger_name ) 
  831.       end 
  832.  
  833.       local skip_cutscene = false 
  834.       if ( extra_data == true ) then 
  835.          skip_cutscene = true 
  836.       end 
  837.  
  838.       -- Don't play the conversation if the cutscene is skipped, because in this case 
  839.       -- Pierce and Shaundi are already in the truck 
  840.       if ( skip_cutscene == false ) then 
  841.          mission_debug( "Starting conversation...", 15 ) 
  842.          -- Have the player tell Pierce that he's loaded the truck 
  843.          audio_play_conversation( TRUCK_LOADED_DIALOG_STREAM, NOT_CALL ) 
  844.          mission_debug( "Conversation complete...", 15 ) 
  845.       end 
  846.  
  847.       -- Don't continue until Shaundi and Pierce are alive 
  848.       repeat 
  849.          thread_yield() 
  850.       until ( ss08_homies_alive() ) 
  851.       mission_debug( "Pierce and Shaundi alive. Coming to cutscene...", 15 ) 
  852.  
  853.       if ( skip_cutscene == false ) then 
  854.          fade_out( 0 ) 
  855. 			teleport( SHAUNDI_NAME, MP.."Pre_Enter_Shaundi", true ) 
  856. 			teleport( PIERCE_NAME, MP.."Pre_Enter_Pierce", true ) 
  857.          -- Hide all the boxes - in theory they should be "inside" the truck now 
  858. 			group_hide( DRUG_BOXES_GROUP ) 
  859. 			group_destroy( DRUG_BOXES_GROUP ) 
  860.  
  861.          -- Hide Pierce and Shaundi so that there won't be any collision between them 
  862.          -- and the cutscene versions 
  863.          character_hide( SHAUNDI_NAME ) 
  864.          character_hide( PIERCE_NAME ) 
  865.          group_hide( DRUG_TRUCK_LOADING_GROUP ) 
  866.          group_destroy( DRUG_TRUCK_LOADING_GROUP ) 
  867.          -- Play the "Pierce and Shaundi board the truck" cutscene 
  868.          cutscene_play( SEATING_CUTSCENE_NAME, DRUG_TRUCK_GROUP, { ARRIVAL_NAVPOINTS[LOCAL_PLAYER], ARRIVAL_NAVPOINTS[REMOTE_PLAYER] } ) 
  869.  
  870.          -- The cutscene system leaves the group lying around for you to play with after the cutscene is done. 
  871.          -- Because we are working with imposters in the cutscene, we need to clean up the imposter group before using the real group. 
  872.          -- I group_hide the group first so that group_destroy will actually destroy the other objects, rather than just release-to-world. 
  873.          group_hide("ss08_$Cutscene") 
  874.          group_destroy("ss08_$Cutscene") 
  875.  
  876.          -- Now that the cutscene is over, unhide the characters used by the cutscene. 
  877.          group_show( DRUG_TRUCK_GROUP ) 
  878.          character_show( SHAUNDI_NAME ) 
  879.          character_show( PIERCE_NAME ) 
  880.       else 
  881.          -- Hide all the boxes - in theory they should be "inside" the truck now 
  882. 			if ( group_is_loaded( DRUG_BOXES_GROUP ) ) then 
  883. 				group_hide( DRUG_BOXES_GROUP ) 
  884. 				group_destroy( DRUG_BOXES_GROUP ) 
  885. 			end 
  886.       end 
  887.  
  888.       -- Create the ambusher group 
  889.       group_show( OUTSIDE_OF_WAREHOUSE_AMBUSHER_GROUP ) 
  890.       for index, name in pairs( OUTSIDE_OF_WAREHOUSE_AMBUSHER_MEMBERS ) do 
  891.          crouch_start( name ) 
  892.          mission_debug( name.." was told to crouch.", 15 ) 
  893.       end 
  894.       trigger_enable( OUTSIDE_OF_WAREHOUSE_AMBUSH_TRIGGER, true ) 
  895.       on_trigger( "ss08_outside_of_warehouse_ambush", OUTSIDE_OF_WAREHOUSE_AMBUSH_TRIGGER ) 
  896.  
  897.       -- Put Shaundi and Pierce in the truck 
  898.       vehicle_speed_override( DRUG_TRUCK, 0 ) 
  899.       vehicle_disable_chase( DRUG_TRUCK ) 
  900.       vehicle_disable_flee( DRUG_TRUCK ) 
  901.       vehicle_door_prevent_damage_detach( DRUG_TRUCK, "Door_BR", true ) 
  902.       vehicle_door_prevent_damage_detach( DRUG_TRUCK, "Door_BL", true ) 
  903.       vehicle_stop( DRUG_TRUCK ) 
  904.       on_vehicle_destroyed( "ss08_drug_truck_destroyed", DRUG_TRUCK ) 
  905.  
  906.       if ( skip_cutscene == false ) then 
  907.          follower_make_independent( PIERCE_NAME, true ) 
  908.          follower_make_independent( SHAUNDI_NAME, true ) 
  909. 			--delay( 2.0 ) 
  910. 			vehicle_enter_teleport( PIERCE_NAME, DRUG_TRUCK, 0 ) 
  911. 			vehicle_enter_teleport( SHAUNDI_NAME, DRUG_TRUCK, 1 ) 
  912.          vehicle_suppress_npc_exit( DRUG_TRUCK, true ) 
  913.          set_unjackable_flag( DRUG_TRUCK, true ) 
  914.       end 
  915.       -- else: Pierce and Shaundi are already in the truck if the cutscene is skipped 
  916.  
  917.       set_ignore_ai_flag( SHAUNDI_NAME, false ) 
  918.       set_ignore_ai_flag( PIERCE_NAME, false ) 
  919.  
  920.       turn_invulnerable( PIERCE_NAME ) 
  921.       turn_invulnerable( SHAUNDI_NAME ) 
  922.       on_death( "", PIERCE_NAME ) 
  923.       on_death( "", SHAUNDI_NAME ) 
  924.  
  925.       -- Let the player know what he should be doing 
  926.       if ( skip_cutscene == false ) then 
  927.          mission_help_table( HT_GET_DRUGS_TO_HQ, "", "", SYNC_ALL ) 
  928.       end 
  929.  
  930.       --mesh_mover_play_action( GARAGE_DOOR, "start2" ) 
  931.       --Garage_door_open = false 
  932.  
  933.       -- Show the player's escape car 
  934.       group_show( ESCAPE_CAR_GROUP ) 
  935.  
  936.       --  
  937.       thread_new( "ss08_check_for_state_change" ) 
  938.  
  939.       ss08_add_vehicle_enter_and_exit_callbacks( "ss08_entered_vehicle_escort_van_initial" ) 
  940.  
  941.       marker_add_vehicle( ESCAPE_CAR_NAME, MINIMAP_ICON_LOCATION, "" ) 
  942.       waypoint_add( ESCAPE_CAR_NAME, SYNC_ALL ) 
  943.       if ( skip_cutscene ) then 
  944.          mission_help_table_nag( HT_GET_A_CAR ) 
  945.       else 
  946.          mission_help_table( HT_GET_A_CAR ) 
  947.       end 
  948.  
  949.       -- Have every living junkie attack the player again, because the cutscene can stop them 
  950. 		ss08_all_living_junkies_attack() 
  951.       mission_set_checkpoint( CP_TRUCK_LOADED ) 
  952.  
  953.    elseif ( new_state == MS_TRAVELING_TO_BASE ) then 
  954.       thread_new( "ss08_maybe_spawn_random_chase_squad" ) 
  955.  
  956.       -- Add truck health display and tracking 
  957.       hud_bar_on(0, "Damage", HT_TRUCK_HEALTH ) 
  958.       hud_bar_set_range(0, 0, 1.0, SYNC_ALL ) 
  959.       hud_bar_set_value(0, 1.0, SYNC_ALL ) 
  960.       set_max_hit_points( DRUG_TRUCK, INITIAL_DRUG_TRUCK_HP ) 
  961.       set_current_hit_points( DRUG_TRUCK, INITIAL_DRUG_TRUCK_HP ) 
  962.       on_take_damage( "ss08_drug_truck_damaged", DRUG_TRUCK ) 
  963.       on_collision( "ss08_drug_truck_damaged", DRUG_TRUCK )  
  964.  
  965.       -- Activate the obstacles and triggers for the trip back to HQ 
  966.       for index, name in pairs( CHASE_SQUAD_GROUP_NAMES ) do 
  967.          local chase_trigger_name = CHASE_SQUAD_TRIGGER_NAMES[index] 
  968.          trigger_enable( chase_trigger_name, true ) 
  969.          on_trigger( "ss08_hit_chase_trigger", chase_trigger_name ) 
  970.       end 
  971.  
  972.       -- Activate the final objective trigger 
  973.       trigger_enable( SAINTS_HQ, true ) 
  974.       on_trigger( "ss08_reached_hq", SAINTS_HQ ) 
  975.       marker_add_trigger( SAINTS_HQ, "", INGAME_EFFECT_VEHICLE_LOCATION, SYNC_ALL ) 
  976.  
  977.       vehicle_infinite_mass( DRUG_TRUCK, true ) 
  978.       set_cant_flee_flag( SHAUNDI_NAME, true ) 
  979.       set_cant_flee_flag( PIERCE_NAME, true ) 
  980.       vehicle_disable_chase( DRUG_TRUCK, true ) 
  981.       vehicle_disable_flee( DRUG_TRUCK, true ) 
  982.       vehicle_set_crazy( DRUG_TRUCK, true ) 
  983.  
  984.       -- Set the truck to pathfind to the Saints HQ 
  985.       vehicle_speed_override( DRUG_TRUCK, DRUG_TRUCK_INITIAL_SPEED_MPH ) 
  986.  
  987.       -- use_navmesh = true, stop_at_goal = false 
  988.       local p1_success = vehicle_pathfind_to( DRUG_TRUCK, BACK_TO_HQ_PATH_INITIAL, true, false ) 
  989.       if ( p1_success == false ) then 
  990.          mission_debug( "Path one failed" ) 
  991.       end 
  992.       vehicle_ignore_repulsors( DRUG_TRUCK, true ) 
  993.  
  994.       -- Require that the player be near the truck, once it gets out of the warehouse area 
  995.       distance_display_on( DRUG_TRUCK, 0, DRUG_TRUCK_MAX_DISTANCE_METERS, 0, DRUG_TRUCK_MAX_DISTANCE_METERS, SYNC_ALL ) 
  996.       on_tailing_good( "ss08_in_range_of_truck" ) 
  997.       on_tailing_too_far( "ss08_out_of_range_of_truck" ) 
  998.  
  999.       for index, path_name in pairs( BACK_TO_HQ_PATHS_MAIN ) do 
  1000.          -- use_navmesh = false, stop_at_goal = false 
  1001.          local p2_success = vehicle_pathfind_to( DRUG_TRUCK, path_name, false, false ) 
  1002.          if ( p2_success == false ) then 
  1003.             mission_debug( "Path two failed" ) 
  1004.          end 
  1005.       end 
  1006.  
  1007.       ss08_add_vehicle_enter_and_exit_callbacks( "", "" ) 
  1008.  
  1009.       -- use_navmesh = true, stop_at_goal = true 
  1010.       local p3_success = vehicle_pathfind_to( DRUG_TRUCK, BACK_TO_HQ_PATH_FINAL, true, true ) 
  1011.       if ( p3_success == false ) then 
  1012.          mission_debug( "Path three failed" ) 
  1013.       end 
  1014.  
  1015.       thread_new( "ss08_check_for_victory" ) 
  1016.    end 
  1017. end 
  1018.  
  1019. function ss08_all_living_junkies_attack() 
  1020. 	-- Go through all the squads in each direction 
  1021. 	for squad_index, squad in ATTACK_SQUADS_MEMBERS do 
  1022. 		-- Go through each member in each squad 
  1023. 		for junkie_index, junkie_name in pairs( squad ) do 
  1024. 			-- If this junkie isn't dead, then have him attack the player 
  1025. 			if ( character_is_released( junkie_name ) == false ) then 
  1026. 				if ( character_is_dead( junkie_name ) == false ) then 
  1027. 					local distance, player = get_dist_closest_player_to_object( junkie_name ) 
  1028. 					attack_safe( junkie_name, player, false ) 
  1029. 				end 
  1030. 			end 
  1031. 		end 
  1032. 	end 
  1033. end 
  1034.  
  1035. function ss08_homies_alive() 
  1036.    if ( character_is_dead( PIERCE_NAME ) ) then 
  1037.       return false 
  1038.    end 
  1039.    if ( character_is_dead( SHAUNDI_NAME ) ) then 
  1040.       return false 
  1041.    end 
  1042.  
  1043.    return true 
  1044. end 
  1045.  
  1046. function ss08_add_vehicle_enter_and_exit_callbacks( enter_callback, exit_callback ) 
  1047.    if ( enter_callback == nil ) then 
  1048.       enter_callback = "" 
  1049.    end 
  1050.    if ( exit_callback == nil ) then 
  1051.       exit_callback = "" 
  1052.    end 
  1053.  
  1054.    -- Player callbacks 
  1055.    on_vehicle_enter( enter_callback, LOCAL_PLAYER ) 
  1056.    on_vehicle_exit( exit_callback, LOCAL_PLAYER ) 
  1057.    if ( coop_is_active() ) then 
  1058.       on_vehicle_enter( enter_callback, REMOTE_PLAYER ) 
  1059.       on_vehicle_exit( exit_callback, REMOTE_PLAYER ) 
  1060.    end 
  1061.  
  1062.    -- Escape vehicle 
  1063.    on_vehicle_enter( enter_callback, ESCAPE_CAR_NAME ) 
  1064.    on_vehicle_exit( exit_callback, ESCAPE_CAR_NAME ) 
  1065.  
  1066.    -- Attack squad vehicles 
  1067.    for index, vehicle_name in pairs( ATTACK_SQUAD_VEHICLES ) do 
  1068.       if ( vehicle_is_destroyed( vehicle_name ) == false ) then 
  1069.          on_vehicle_enter( enter_callback, vehicle_name ) 
  1070.          on_vehicle_exit( exit_callback, vehicle_name ) 
  1071.       end 
  1072.    end 
  1073.  
  1074.    -- Chase squad vehicles 
  1075.    for index, vehicle_name in pairs( CHASE_SQUAD_GROUP_VEHICLES ) do 
  1076.       if ( vehicle_is_destroyed( vehicle_name ) == false ) then 
  1077.          on_vehicle_enter( enter_callback, vehicle_name ) 
  1078.          on_vehicle_exit( exit_callback, vehicle_name ) 
  1079.       end 
  1080.    end 
  1081. end 
  1082.  
  1083. function ss08_path_ambush_01( triggerer_name, trigger_name ) 
  1084.    if ( triggerer_name == SHAUNDI_NAME or triggerer_name == PIERCE_NAME or 
  1085.         triggerer_name == LOCAL_PLAYER or triggerer_name == REMOTE_PLAYER ) then 
  1086.       trigger_enable( trigger_name, false ) 
  1087.  
  1088.       for index, name in pairs( PATH_AMBUSHER_GROUPS_MEMBERS[1] ) do 
  1089.          attack_safe( name, triggerer_name, false ) 
  1090.       end 
  1091.    end 
  1092. end 
  1093.  
  1094. function ss08_path_ambush_02( triggerer_name, trigger_name ) 
  1095.    if ( triggerer_name == SHAUNDI_NAME or triggerer_name == PIERCE_NAME or 
  1096.         triggerer_name == LOCAL_PLAYER or triggerer_name == REMOTE_PLAYER ) then 
  1097.       trigger_enable( trigger_name, false ) 
  1098.  
  1099.       for index, name in pairs( PATH_AMBUSHER_GROUPS_MEMBERS[1] ) do 
  1100.          attack_safe( name, triggerer_name, false ) 
  1101.       end 
  1102.    end 
  1103. end 
  1104.  
  1105. -- Called when the "outside of warehouse ambush" trigger is hit - causes the- 
  1106. -- ambushers lurking outside to attack the van. 
  1107. -- 
  1108. function ss08_outside_of_warehouse_ambush( triggerer_name, trigger_name ) 
  1109.    if ( triggerer_name == SHAUNDI_NAME or triggerer_name == PIERCE_NAME or 
  1110.         triggerer_name == LOCAL_PLAYER or triggerer_name == REMOTE_PLAYER ) then 
  1111.  
  1112.       mission_debug( "ambush triggered by "..triggerer_name ) 
  1113.  
  1114.       trigger_enable( trigger_name, false ) 
  1115.  
  1116.       for index, name in pairs( OUTSIDE_OF_WAREHOUSE_AMBUSHER_MEMBERS ) do 
  1117.          thread_new( "ss08_ambusher_ambush_truck", name, AMBUSHER_GOALS[index] ) 
  1118.       end 
  1119.    end 
  1120. end 
  1121.  
  1122. function ss08_ambusher_ambush_truck( ambusher_name, ambusher_goal ) 
  1123.    npc_leash_remove( ambusher_name ) 
  1124.    crouch_stop( ambusher_name ) 
  1125.  
  1126.    attack_safe( ambusher_name, PIERCE_NAME, false ) 
  1127.  
  1128.    -- speed = run, retry_on_failure = false, move_and_fire = true 
  1129.    move_to( ambusher_name, ambusher_goal, 2, false, true ) 
  1130. end 
  1131.  
  1132.  
  1133. function ss08_entered_vehicle_during_escort( character_name, vehicle_name ) 
  1134.    Players_in_vehicle[character_name] = true 
  1135.    mission_debug( character_name.." entered vehicle" ) 
  1136.  
  1137.    -- Add a callback for this vehicle if it's a script one. The random chase 
  1138.    -- vehicles need their exit callbacks set to something else initially. 
  1139.    if ( vehicle_name ~= nil ) then 
  1140.       on_vehicle_exit( "ss08_left_vehicle_during_escort", vehicle_name ) 
  1141.    end 
  1142.  
  1143.    if ( ss08_all_players_in_of_range_of_truck() and 
  1144.         ss08_all_players_in_vehicle() ) then 
  1145.       mission_debug( "Drug truck resuming" ) 
  1146.       vehicle_speed_override( DRUG_TRUCK, DRUG_TRUCK_DESIRED_SPEED_MPH ) 
  1147.       Truck_waiting = false 
  1148.    end 
  1149. end 
  1150.  
  1151. function ss08_left_vehicle_during_escort( character_name ) 
  1152.    Players_in_vehicle[character_name] = false 
  1153.    if ( ss08_all_players_in_vehicle() == false ) then 
  1154.       mission_debug( "Left vehicle" ) 
  1155.       ss08_maybe_truck_start_waiting() 
  1156.    end 
  1157. end 
  1158.  
  1159. function ss08_entered_vehicle_escort_van_initial( character_name ) 
  1160.    -- Update the "player in vehicle" status for both players 
  1161.    if ( character_is_in_vehicle( LOCAL_PLAYER ) ) then 
  1162.       Players_in_vehicle[LOCAL_PLAYER] = true 
  1163.    end 
  1164.    if ( coop_is_active() and character_is_in_vehicle( REMOTE_PLAYER ) ) then 
  1165.       Players_in_vehicle[REMOTE_PLAYER] = true 
  1166.    end 
  1167.    -- Update the "player in range of truck" status for both players 
  1168.    if ( get_dist( LOCAL_PLAYER, DRUG_TRUCK ) < DRUG_TRUCK_MAX_DISTANCE_METERS ) then 
  1169.       Players_in_range_of_drug_truck[LOCAL_PLAYER] = true 
  1170.    end 
  1171.    if ( coop_is_active() and get_dist( REMOTE_PLAYER, DRUG_TRUCK ) < DRUG_TRUCK_MAX_DISTANCE_METERS ) then 
  1172.       Players_in_range_of_drug_truck[REMOTE_PLAYER] = true 
  1173.    end 
  1174.  
  1175.    Players_in_vehicle[character_name] = true 
  1176.  
  1177.    ss08_add_vehicle_enter_and_exit_callbacks( "ss08_entered_vehicle_during_escort", 
  1178.                                               "ss08_left_vehicle_during_escort" ) 
  1179.  
  1180.    marker_remove_vehicle( ESCAPE_CAR_NAME ) 
  1181.    waypoint_remove( SYNC_ALL ) 
  1182.  
  1183.    mission_help_table( HT_ESCORT_TRUCK_TO_HIDEOUT ) 
  1184.    marker_add_vehicle( DRUG_TRUCK, MINIMAP_ICON_PROTECT_ACQUIRE, INGAME_EFFECT_VEHICLE_PROTECT_ACQUIRE, SYNC_ALL ) 
  1185. end 
  1186.  
  1187. function ss08_check_for_victory() 
  1188.    while ( get_dist_char_to_nav( PIERCE_NAME, SAINTS_HQ ) > TO_HQ_WIN_DISTANCE_METERS ) do 
  1189.       delay( 0 ) 
  1190.    end 
  1191.  
  1192.    Mission_won = true 
  1193.    mission_end_success( MISSION_NAME, CT_OUTRO ) 
  1194. end 
  1195.  
  1196. function ss08_check_for_state_change() 
  1197.    local neither_player_in_vehicle_and_in_range = true 
  1198.  
  1199.    while ( neither_player_in_vehicle_and_in_range ) do 
  1200.       --  
  1201.       local distance = get_dist_char_to_nav( LOCAL_PLAYER, DRUG_TRUCK )  
  1202.       if ( distance < DRUG_TRUCK_MAX_DISTANCE_METERS ) then 
  1203.          local vehicle_type = get_char_vehicle_type( LOCAL_PLAYER ) 
  1204.          if ( vehicle_type ~= VT_NONE ) then 
  1205.             neither_player_in_vehicle_and_in_range = false 
  1206.          end 
  1207.       end 
  1208.  
  1209.       if ( coop_is_active() and neither_player_in_vehicle_and_in_range ) then 
  1210.          distance = get_dist_char_to_nav( REMOTE_PLAYER, DRUG_TRUCK )  
  1211.          if ( distance < DRUG_TRUCK_MAX_DISTANCE_METERS ) then 
  1212.             local vehicle_type = get_char_vehicle_type( REMOTE_PLAYER ) 
  1213.             if ( vehicle_type ~= VT_NONE ) then 
  1214.                neither_player_in_vehicle_and_in_range = false 
  1215. 	         end 
  1216.          end 
  1217.       end 
  1218.  
  1219.       delay( 0 ) 
  1220.    end 
  1221.  
  1222. 	mission_debug( "switching to state MS_TRAVELING_TO_BASE from check_for_state_change", 15 ) 
  1223.    ss08_switch_state( MS_TRAVELING_TO_BASE ) 
  1224. end 
  1225.  
  1226. function ss08_maybe_truck_start_waiting() 
  1227.    if ( Truck_waiting == false ) then 
  1228.       mission_debug( "Drug truck waiting" ) 
  1229.       mission_help_table( HT_PIERCE_WAITING_ON_YOU, SYNC_ALL ) 
  1230.       vehicle_speed_override( DRUG_TRUCK, 0 ) 
  1231.       Truck_waiting = true 
  1232.    end 
  1233. end 
  1234.  
  1235. function ss08_in_range_of_truck( triggerer_name ) 
  1236.    mission_debug( triggerer_name.." in range" ) 
  1237.    Players_in_range_of_drug_truck[triggerer_name] = true 
  1238.  
  1239.    if ( ss08_all_players_in_of_range_of_truck() and 
  1240.         ss08_all_players_in_vehicle() ) then 
  1241.       vehicle_speed_override( DRUG_TRUCK, DRUG_TRUCK_DESIRED_SPEED_MPH ) 
  1242.       Truck_waiting = false 
  1243.    end 
  1244. end 
  1245.  
  1246. function ss08_out_of_range_of_truck( triggerer_name ) 
  1247.    mission_debug( triggerer_name.." out of range" ) 
  1248.    Players_in_range_of_drug_truck[triggerer_name] = false 
  1249.  
  1250.    ss08_maybe_truck_start_waiting() 
  1251. end 
  1252.  
  1253. function ss08_get_chase_group_index_from_trigger_name( trigger_name ) 
  1254.    for index, name in pairs( CHASE_SQUAD_TRIGGER_NAMES ) do 
  1255.       if ( name == trigger_name ) then 
  1256.          return index 
  1257.       end 
  1258.    end 
  1259.    return nil 
  1260. end 
  1261.  
  1262. function ss08_get_vehicle_group_index_from_name( vehicle_name ) 
  1263.    for index, name in pairs( CHASE_SQUAD_GROUP_VEHICLES ) do 
  1264.       if ( name == vehicle_name ) then 
  1265.          return index 
  1266.       end 
  1267.    end 
  1268.  
  1269.    for index, name in pairs( RANDOM_CHASE_SQUAD_VEHICLES ) do 
  1270.       if ( name == vehicle_name ) then 
  1271.          return index + NUM_CHASE_SQUADS 
  1272.       end 
  1273.    end 
  1274.    return nil 
  1275. end 
  1276.  
  1277. function ss08_get_npc_group_index_from_name( npc_name ) 
  1278.    for group_index, npc_list in pairs ( CHASE_SQUAD_GROUP_MEMBERS ) do 
  1279.       for index, name in pairs( npc_list ) do 
  1280.          if ( name == npc_name ) then 
  1281.             return group_index 
  1282.          end 
  1283.       end 
  1284.    end 
  1285.  
  1286.    for group_index, npc_list in pairs( RANDOM_CHASE_SQUAD_MEMBERS ) do 
  1287.       for index, name in pairs( npc_list ) do 
  1288.          if ( name == npc_name ) then 
  1289.             return group_index + NUM_CHASE_SQUADS 
  1290.          end 
  1291.       end 
  1292.    end 
  1293.  
  1294.    return nil 
  1295. end 
  1296.  
  1297. function ss08_hit_chase_trigger( triggerer_name, trigger_name ) 
  1298.    ss08_maybe_spawn_random_chase_squad() 
  1299.    trigger_enable( trigger_name, false ) 
  1300.    --[[ 
  1301.    if ( Num_chasing_cars < MAX_CHASING_CARS ) then 
  1302.       -- Disable the trigger so that this chase group only spawns once! 
  1303.       trigger_enable( trigger_name, false ) 
  1304.  
  1305.       -- Find out which group we should spawn for this trigger 
  1306.       local group_index = ss08_get_chase_group_index_from_trigger_name( trigger_name ) 
  1307.  
  1308.       Chase_squad_cars_chasing[group_index] = true 
  1309.  
  1310.       --  
  1311.       group_show( CHASE_SQUAD_GROUP_NAMES[group_index] ) 
  1312.       vehicle_enter_group_teleport( CHASE_SQUAD_GROUP_MEMBERS[group_index], CHASE_SQUAD_GROUP_VEHICLES[group_index] ) 
  1313.  
  1314.       on_vehicle_destroyed( "ss08_chase_car_destroyed", CHASE_SQUAD_GROUP_VEHICLES[group_index] ) 
  1315.       on_vehicle_exit( "ss08_attacker_leaves_chase_car", CHASE_SQUAD_GROUP_VEHICLES[group_index] ) 
  1316.  
  1317.       delay( 0 ) 
  1318.       local driver = get_char_in_vehicle( CHASE_SQUAD_GROUP_VEHICLES[group_index], 0) 
  1319.       on_death( "ss08_chase_car_driver_killed", driver ) 
  1320.  
  1321.       --  
  1322. --      local distance 
  1323. --      local player 
  1324. --      distance, player = get_dist_closest_player_to_object( driver ) 
  1325.       attack_safe( driver, SHAUNDI_NAME, false ) 
  1326.       Num_chasing_cars = Num_chasing_cars + 1 
  1327.    end 
  1328.    ]] 
  1329. end 
  1330.  
  1331. function ss08_find_nearest_chase_trigger_to_drug_truck() 
  1332.    local closest_location = RANDOM_CHASE_SQUAD_SPAWN_LOCATIONS[1] 
  1333.    local closest_dist = get_dist( DRUG_TRUCK, closest_location ) 
  1334.  
  1335.    for index, nav_name in pairs( RANDOM_CHASE_SQUAD_SPAWN_LOCATIONS ) do 
  1336.       local cur_dist = get_dist( DRUG_TRUCK, nav_name ) 
  1337.       if ( cur_dist <= closest_dist --[[and ss08_navpoint_out_of_players_fov( nav_name )]] ) then 
  1338.          closest_dist = cur_dist 
  1339.          closest_location = nav_name 
  1340.       end 
  1341.    end 
  1342.  
  1343.    return closest_location 
  1344. end 
  1345.  
  1346. function ss08_maybe_spawn_random_chase_squad() 
  1347.    mission_debug( "rc spawning - waiting" ) 
  1348.    -- Only spawn one squad at a time in order to prevent overlap 
  1349.    repeat 
  1350.       thread_yield() 
  1351.    until ( Group_spawning == false ) 
  1352.  
  1353.    if ( Num_chasing_cars < MAX_CHASING_CARS ) then 
  1354.       Num_chasing_cars = Num_chasing_cars + 1 
  1355.  
  1356.       mission_debug( "rc spawning - started", 15 ) 
  1357.  
  1358.       Group_spawning = true 
  1359.       delay( RANDOM_CHASE_SQUAD_SPAWN_INTERVAL_SECONDS ) 
  1360.  
  1361.       -- Choose and create one of the chase groups 
  1362.       local group_index = Last_random_chase_group_index + 1 
  1363.       if ( group_index > RANDOM_CHASE_SQUAD_COUNT ) then 
  1364.          group_index = 1 
  1365.       end 
  1366.  
  1367.       -- We record the random chase squads after the chase squads in the list 
  1368.       -- of chasing cars 
  1369.       Chase_squad_cars_chasing[group_index + NUM_CHASE_SQUADS] = true 
  1370.  
  1371.       local group_to_load = RANDOM_CHASE_SQUAD_GROUPS[group_index] 
  1372.       mission_debug( "rc spawning - decided to load group "..group_to_load, 15 ) 
  1373.       if ( group_is_loaded( group_to_load ) ) then 
  1374.          release_to_world( group_to_load ) 
  1375.       end 
  1376.  
  1377.       group_create( group_to_load, true ) 
  1378.       mission_debug( "rc spawning - loaded group "..group_to_load, 15 ) 
  1379.  
  1380.       local member_count = sizeof_table( RANDOM_CHASE_SQUAD_MEMBERS[group_index] ) 
  1381.       local num_with_heavy_weapons = rand_int( 2, member_count ) 
  1382.       local num_with_light_weapons = member_count - num_with_heavy_weapons 
  1383.  
  1384.       -- Arm the members of the chase squad 
  1385.       local function give_random_weapon( member_name, weapon_types ) 
  1386.          local weapon_index = rand_int( 1, sizeof_table( weapon_types ) ) 
  1387.          inv_item_add( weapon_types[weapon_index], 1, member_name ) 
  1388.          inv_item_add_ammo( member_name, weapon_types[weapon_index], 100 ) 
  1389.       end 
  1390.       for index, member_name in pairs( RANDOM_CHASE_SQUAD_MEMBERS[group_index] ) do 
  1391.          if ( index <= num_with_heavy_weapons ) then 
  1392.             give_random_weapon( member_name, CHASE_SQUAD_HEAVY_WEAPONS ) 
  1393.          else 
  1394.             give_random_weapon( member_name, CHASE_SQUAD_LIGHT_WEAPONS ) 
  1395.          end 
  1396.          give_random_weapon( member_name, CHASE_SQUAD_THROWN_WEAPONS ) 
  1397.       end 
  1398.  
  1399.       --  
  1400.       vehicle_enter_group_teleport( RANDOM_CHASE_SQUAD_MEMBERS[group_index], 
  1401.                                     RANDOM_CHASE_SQUAD_VEHICLES[group_index] ) 
  1402.  
  1403.       on_vehicle_enter( "ss08_entered_vehicle_during_escort", RANDOM_CHASE_SQUAD_VEHICLES[group_index] ) 
  1404.  
  1405.       on_vehicle_destroyed( "ss08_chase_car_destroyed", RANDOM_CHASE_SQUAD_VEHICLES[group_index] ) 
  1406.       on_vehicle_exit( "ss08_attacker_leaves_chase_car", RANDOM_CHASE_SQUAD_VEHICLES[group_index] ) 
  1407.  
  1408.       -- Wait for the driver to be seated 
  1409.       delay( 0 ) 
  1410.       local driver = get_char_in_vehicle( RANDOM_CHASE_SQUAD_VEHICLES[group_index], 0) 
  1411.       on_death( "ss08_chase_car_driver_killed", driver ) 
  1412.  
  1413.       -- Teleport the chase squad vehicle to the location and give chase 
  1414.       -- Find the nearest chase trigger 
  1415.       local location = ss08_find_nearest_chase_trigger_to_drug_truck() 
  1416.  
  1417.       teleport_vehicle( RANDOM_CHASE_SQUAD_VEHICLES[group_index], location ) 
  1418.       mission_debug( "rc attacking" ) 
  1419.       for index, member_name in pairs( RANDOM_CHASE_SQUAD_MEMBERS[group_index] ) do 
  1420.          attack_safe( member_name, PIERCE_NAME, false ) 
  1421.       end 
  1422.  
  1423.       Last_random_chase_group_index = group_index 
  1424.  
  1425.       -- Give the car some time to start chasing 
  1426.       mission_debug( "rc delay" ) 
  1427.       delay( 3.0 ) 
  1428.       Group_spawning = false 
  1429.       mission_debug( "rc spawning - done", 15 ) 
  1430.    end 
  1431. end 
  1432.  
  1433. function ss08_chase_car_removed( group_index ) 
  1434.    Num_chasing_cars = Num_chasing_cars - 1 
  1435.    Chase_squad_cars_chasing[group_index] = false 
  1436.  
  1437.    ss08_maybe_spawn_random_chase_squad() 
  1438. end 
  1439.  
  1440. function ss08_chase_car_driver_killed( driver_name ) 
  1441.    -- If a chase car's driver is killed, then remove the car's destroyed callback 
  1442.    local group_index = ss08_get_npc_group_index_from_name( driver_name ) 
  1443.  
  1444.    if ( Chase_squad_cars_chasing[group_index] ) then 
  1445.       if ( group_index <= NUM_CHASE_SQUADS ) then 
  1446.          on_vehicle_destroyed( "", CHASE_SQUAD_GROUP_VEHICLES[group_index] ) 
  1447.          on_vehicle_exit( "", CHASE_SQUAD_GROUP_VEHICLES[group_index] ) 
  1448.          -- Remove the exit  
  1449.          for index, member_name in CHASE_SQUAD_GROUP_MEMBERS[group_index] do 
  1450.             on_death( "", member_name ) 
  1451.          end 
  1452.       else 
  1453.          local rc_group_index = group_index - NUM_CHASE_SQUADS 
  1454.          on_vehicle_destroyed( "", RANDOM_CHASE_SQUAD_VEHICLES[rc_group_index] ) 
  1455.          on_vehicle_exit( "ss08_left_vehicle_during_escort", RANDOM_CHASE_SQUAD_VEHICLES[rc_group_index] ) 
  1456.          -- Remove the exit  
  1457.          for index, member_name in RANDOM_CHASE_SQUAD_MEMBERS[rc_group_index] do 
  1458.             on_death( "", member_name ) 
  1459.          end 
  1460.       end 
  1461.  
  1462.       ss08_chase_car_removed( group_index ) 
  1463.    end 
  1464. end 
  1465.  
  1466. function ss08_attacker_leaves_chase_car( attacker, chase_car ) 
  1467.    local group_index = ss08_get_vehicle_group_index_from_name( chase_car ) 
  1468.  
  1469.    if ( Chase_squad_cars_chasing[group_index] ) then 
  1470.       on_vehicle_destroyed( "", chase_car ) 
  1471.       on_vehicle_exit( "ss08_left_vehicle_during_escort", chase_car ) 
  1472.  
  1473.       if ( group_index <= NUM_CHASE_SQUADS ) then 
  1474.          -- Remove callbacks on every member... should get the driver :) 
  1475.          for index, member_name in CHASE_SQUAD_GROUP_MEMBERS[group_index] do 
  1476.             on_death( "", member_name ) 
  1477.          end 
  1478.       else 
  1479.          local rc_group_index = group_index - NUM_CHASE_SQUADS 
  1480.  
  1481.          -- Remove callbacks on every member... should get the driver :) 
  1482.          for index, member_name in RANDOM_CHASE_SQUAD_MEMBERS[rc_group_index] do 
  1483.             on_death( "", member_name ) 
  1484.          end 
  1485.       end 
  1486.  
  1487.       ss08_chase_car_removed( group_index ) 
  1488.    end 
  1489. end 
  1490.  
  1491. function ss08_chase_car_destroyed( vehicle_name ) 
  1492.    -- If a chase car is destroyed, then remove its driver's callback 
  1493.    local group_index = ss08_get_vehicle_group_index_from_name( vehicle_name ) 
  1494.  
  1495.    if ( Chase_squad_cars_chasing[group_index] ) then 
  1496.  
  1497.       if ( group_index <= NUM_CHASE_SQUADS ) then 
  1498.          on_vehicle_exit( "", CHASE_SQUAD_GROUP_VEHICLES[group_index] ) 
  1499.          -- Remove callbacks on every member... should get the driver :) 
  1500.          for index, member_name in CHASE_SQUAD_GROUP_MEMBERS[group_index] do 
  1501.             on_death( "", member_name ) 
  1502.          end 
  1503.       else 
  1504.          local rc_group_index = group_index - NUM_CHASE_SQUADS 
  1505.          on_vehicle_exit( "", RANDOM_CHASE_SQUAD_VEHICLES[rc_group_index] ) 
  1506.  
  1507.          -- Remove callbacks on every member... should get the driver :) 
  1508.          for index, member_name in RANDOM_CHASE_SQUAD_MEMBERS[rc_group_index] do 
  1509.             on_death( "", member_name ) 
  1510.          end 
  1511.       end 
  1512.  
  1513.       ss08_chase_car_removed( group_index ) 
  1514.    end 
  1515. end 
  1516.  
  1517. function ss08_drug_truck_destroyed() 
  1518.    mission_end_failure( MISSION_NAME, HT_TRUCK_DESTROYED ) 
  1519. end 
  1520.  
  1521. function ss08_drug_truck_damaged() 
  1522.    local cur_truck_hp = get_current_hit_points( DRUG_TRUCK ) 
  1523.    local percent_remaining = cur_truck_hp / INITIAL_DRUG_TRUCK_HP 
  1524.  
  1525.    hud_bar_set_value(0, percent_remaining, SYNC_ALL ) 
  1526. end 
  1527.  
  1528. function ss08_reached_hq( triggerer_name, trigger_name ) 
  1529.    -- Check to see if the person who triggered it is in the drug truck 
  1530.    local character_driving_drug_truck = get_char_in_vehicle( DRUG_TRUCK, 0 ) 
  1531.    -- If so, we win the mission 
  1532.    if ( character_driving_drug_truck == triggerer_name ) then 
  1533.       audio_play_conversation( END_MISSION_DIALOG_STREAM, NOT_CALL ) 
  1534.       Mission_won = true 
  1535.       mission_end_success( MISSION_NAME, CT_OUTRO ) 
  1536.    end 
  1537. end 
  1538.  
  1539. -- This function gets Pierce to leave the warehouse, obstensibly to get a 
  1540. -- truck to cart the drugs away with. 
  1541. -- 
  1542. function ss08_pierce_leaves() 
  1543.    -- Have Pierce leave the player 
  1544.    turn_invulnerable( PIERCE_NAME ) 
  1545. 	thread_yield() 
  1546.    on_dismiss( "", PIERCE_NAME ) 
  1547.    party_dismiss( PIERCE_NAME ) 
  1548.    set_ignore_ai_flag( PIERCE_NAME, true ) 
  1549.    character_prevent_flinching( PIERCE_NAME, true ) 
  1550.    character_prevent_explosion_fling( PIERCE_NAME, true ) 
  1551.    character_prevent_kneecapping( PIERCE_NAME, true ) 
  1552. 	if ( crouch_is_crouching( PIERCE_NAME ) ) then 
  1553. 		crouch_stop( PIERCE_NAME ) 
  1554. 		delay( 0.5 ) 
  1555. 	end 
  1556. 	-- Set up the "where's Pierce" audio line 
  1557.    thread_new( "ss08_where_is_pierce_delay" ) 
  1558.  
  1559.    -- Pathfind him to a location 
  1560.    local run = 2 
  1561.    local retry_on_failure = true 
  1562.    local move_and_fire = false 
  1563.    move_to( PIERCE_NAME, PIERCE_GET_TRUCK_PATH, run, retry_on_failure, move_and_fire ) 
  1564.    -- Hide him 
  1565.    character_hide( PIERCE_NAME ) 
  1566.    Pierce_leaves_thread_handle = INVALID_THREAD_HANDLE 
  1567.  
  1568.    character_prevent_flinching( PIERCE_NAME, false ) 
  1569.    character_prevent_explosion_fling( PIERCE_NAME, false ) 
  1570.    character_prevent_kneecapping( PIERCE_NAME, false ) 
  1571. end 
  1572.  
  1573. -- Delay before Shaundi wonders where Pierce is. 
  1574. -- 
  1575. function ss08_where_is_pierce_delay() 
  1576.    local where_is_pierce_time_seconds = WHERE_IS_PIERCE_MESSAGE_DELAY_SECONDS 
  1577.    while ( where_is_pierce_time_seconds > 0 ) do 
  1578.       where_is_pierce_time_seconds = where_is_pierce_time_seconds - get_frame_time() 
  1579.       delay( 0 ) 
  1580.    end 
  1581.  
  1582.    -- Shaundi complains 
  1583.    audio_play_for_character( SHAUNDI_WHATS_TAKING_SO_LONG_LINE, SHAUNDI_NAME, "voice", false, false ) 
  1584. end 
  1585.  
  1586. -- This function is called when Pierce is due to return. It causes him to come back 
  1587. -- and spawns the truck that the player uses to escape with the drugs. 
  1588. -- 
  1589. function ss08_pierce_returns() 
  1590. 	--repeat 
  1591. 	--	thread_yield() 
  1592. 	--until ( thread_check_done( Pierce_leaves_thread_handle ) == true ) 
  1593.  
  1594. 	if ( Pierce_has_returned == false ) then 
  1595. 		Pierce_has_returned = true 
  1596.  
  1597. 		mission_debug( "switching to state MS_LOADING_TRUCK from pierce_returns", 15 ) 
  1598. 		ss08_switch_state( MS_LOADING_TRUCK ) 
  1599. 	end 
  1600. end 
  1601.  
  1602. -- Callback when the truck has been loaded. 
  1603. -- TBD: by a timer or by the homies collecting sufficient drugs 
  1604. -- 
  1605. function ss08_truck_loaded() 
  1606.    objective_text_clear( 0 ) 
  1607.  
  1608. 	mission_debug( "switching to state MS_TRUCK_LOADED from truck_loaded", 15 ) 
  1609.    ss08_switch_state( MS_TRUCK_LOADED ) 
  1610. end 
  1611.  
  1612. -- Returns the index of the next un-collected drug box. 
  1613. -- 
  1614. function ss08_get_next_drug_box_index() 
  1615.    return ( NUM_DRUG_BOXES - Cur_drug_boxes_remaining ) + 1 
  1616. end 
  1617.  
  1618. function ss08_homie_load_drugs( homie_name ) 
  1619.    -- Check to see if enough packages have been queued to be dropped of 
  1620.       -- If so, stop loading. 
  1621.       -- If not, repeat... 
  1622.    while ( Drug_boxes_queued + Drug_boxes_loaded < NUM_DRUG_BOXES ) do 
  1623.       local target_box = nil 
  1624.       -- Target a package that's not currently targeted 
  1625.       for index, box_name in pairs( DRUG_BOXES ) do 
  1626.          if ( Whos_carrying_drug_boxes[box_name] == nil ) then 
  1627.             target_box = box_name 
  1628.             Whos_carrying_drug_boxes[box_name] = homie_name 
  1629.             break 
  1630.          end 
  1631.       end 
  1632.       if ( target_box == nil ) then 
  1633.          return 
  1634.       end 
  1635.       Drug_boxes_queued = Drug_boxes_queued + 1 
  1636.  
  1637.       local walk = 1 
  1638.       local run = 2 
  1639.       local retry_on_failure = true 
  1640.       local move_and_fire = false 
  1641.       -- Run toward the package 
  1642.       move_to( homie_name, BOX_PICKUP_NAV, run, retry_on_failure, move_and_fire ) 
  1643.  
  1644.       -- Pick up the package 
  1645. 	   item_wield( target_box, homie_name, false ) 
  1646.  
  1647.       -- Walk toward the dropoff 
  1648.       move_to( homie_name, BOX_DROPOFFS[homie_name], walk, retry_on_failure, move_and_fire ) 
  1649.  
  1650.       if ( character_is_dead( homie_name ) ) then 
  1651.          return 
  1652.       end 
  1653.  
  1654.       -- Drop off the package 
  1655.       turn_to( homie_name, BOX_LOADING_TARGET ) 
  1656.       item_throw( homie_name, BOX_LOADING_TARGET ) 
  1657.       delay( 2.0 ) 
  1658.  
  1659. --      item_drop( target_box, homie_name ) 
  1660. --      BOX_LOADING_TARGET 
  1661. --      item_hide( target_box ) 
  1662.       Whos_carrying_drug_boxes[target_box] = DRUG_TRUCK 
  1663.  
  1664.       -- Mark the package as dropped off and inform the mission (help text, etc) 
  1665.       Drug_boxes_queued = Drug_boxes_queued - 1 
  1666.       Drug_boxes_loaded = Drug_boxes_loaded + 1 
  1667.       objective_text( 0, HT_X_OF_Y_BOXES_LOADED, Drug_boxes_loaded, NUM_DRUG_BOXES ) 
  1668.  
  1669.       if ( Drug_boxes_loaded == NUM_DRUG_BOXES ) then 
  1670.          ss08_truck_loaded() 
  1671.       end 
  1672.    end 
  1673. end 
  1674.  
  1675. -- This function begins the junkie attack and sets us the callbacks such that 
  1676. -- the attack will continue until the player escapes with the truck. 
  1677. -- 
  1678. function ss08_start_junkie_attack() 
  1679.    -- Calculate which attack squad we should be attacking with 
  1680.    ss08_attack_squad_spawn( SOUTH ) 
  1681.  
  1682.    -- Set death tracking up 
  1683.    ss08_add_death_tracking( SOUTH ) 
  1684.  
  1685.    -- Have the west squad come and attack 
  1686.    ss08_attack_squad_attack( SOUTH ) 
  1687.  
  1688.    -- Set up time to be allowed to attack from another direction 
  1689.    --thread_new( "ss08_other_direction_allowed_delay" ) 
  1690.    Cur_attack_directions[1] = SOUTH 
  1691.  
  1692.    Assault_turned_on = true 
  1693. end 
  1694.  
  1695. -- Adds death tracking for junkie attack squads. 
  1696. -- 
  1697. -- attack_direction: The direction of the squad to add callbacks for 
  1698. -- 
  1699. function ss08_add_death_tracking( attack_direction ) 
  1700.    for index, name in pairs( ATTACK_SQUADS_MEMBERS[attack_direction] ) do 
  1701.       Cur_attackers_remaining = Cur_attackers_remaining + 1 
  1702.       on_death( "ss08_squad_member_died", name ) 
  1703.    end 
  1704.    mission_debug( "Cur_attackers_remaining = "..Cur_attackers_remaining..".", 5 ) 
  1705. end 
  1706.  
  1707. -- Gets the next dropoff point in the list. Once the list runs out, 
  1708. -- starts getting from the beginning of the list. 
  1709. -- 
  1710. -- attack_direction: Which direction the dropoff point should be 
  1711. --                   located in. 
  1712. -- 
  1713. function ss08_get_next_dropoff_point( attack_direction ) 
  1714.    -- Find the next dropoff index in this direction based on the previous one 
  1715.    local next_dropoff_index_in_direction = Last_dropoff_indices[attack_direction] + 1 
  1716.  
  1717.    -- Check to see if this is in range 
  1718.    if ( next_dropoff_index_in_direction > DROPOFF_COUNTS[attack_direction] ) then 
  1719.       -- Out-of-range - roll over the counter 
  1720.       next_dropoff_index_in_direction = 1 
  1721.    end 
  1722.  
  1723.    local next_dropoff_point = DROPOFF_POINTS[attack_direction][next_dropoff_index_in_direction] 
  1724.  
  1725.    -- We've found the index of the next dropoff point - update the last dropoff index used for this 
  1726.    -- direction 
  1727.    Last_dropoff_indices[attack_direction] = next_dropoff_index_in_direction 
  1728.  
  1729.    return next_dropoff_point 
  1730. end 
  1731.  
  1732. function ss08_navpoint_out_of_players_fov( navpoint_name ) 
  1733.    if ( navpoint_in_player_fov( navpoint_name, LOCAL_PLAYER ) == false ) then 
  1734.       if ( coop_is_active() ) then 
  1735.          if ( navpoint_in_player_fov( navpoint_name, REMOTE_PLAYER ) == false ) then 
  1736.             return true 
  1737.          end 
  1738.       else 
  1739.          return true 
  1740.       end 
  1741.    end 
  1742.  
  1743.    return false 
  1744. end 
  1745.  
  1746. function ss08_attack_squad_spawn( attack_direction ) 
  1747.    group_create_hidden( ALL_ATTACK_SQUADS[attack_direction], true ) 
  1748. end 
  1749.  
  1750. function ss08_attack_squad_attack( attack_direction ) 
  1751.    -- Have the members board the car 
  1752.    vehicle_enter_group_teleport( ATTACK_SQUADS_MEMBERS[attack_direction], 
  1753.                                  ATTACK_SQUAD_VEHICLES[attack_direction] ) 
  1754.  
  1755.    repeat 
  1756.       thread_yield() 
  1757.    until ( ss08_all_players_in_warehouse_area() or 
  1758.            ss08_navpoint_out_of_players_fov( ATTACK_SQUAD_VEHICLES[attack_direction] ) ) 
  1759.  
  1760.    -- Make the squad visible 
  1761.    group_show( ALL_ATTACK_SQUADS[attack_direction] ) 
  1762.  
  1763.    -- Lead it along the initial path 
  1764.    vehicle_pathfind_to( ATTACK_SQUAD_VEHICLES[attack_direction], 
  1765.                         ATTACK_VEHICLE_PATHS[attack_direction], true, false ) 
  1766.  
  1767.    -- Select a dropoff point 
  1768.    local dropoff_point = ss08_get_next_dropoff_point( attack_direction ) 
  1769.  
  1770.    mission_debug( "Direction: "..attack_direction.." squad pathing to dropoff "..dropoff_point, 15 ) 
  1771.  
  1772.    -- Have it pathfind here 
  1773.    vehicle_pathfind_to( ATTACK_SQUAD_VEHICLES[attack_direction], 
  1774.                         dropoff_point, true, true ) 
  1775.  
  1776.    -- Have the vehicle inhabitants attack 
  1777.    for index, member in pairs( ATTACK_SQUADS_MEMBERS[attack_direction] ) do 
  1778.       thread_new( "ss08_member_do_attack", member ) 
  1779.    end 
  1780.  
  1781.    -- Release the car to the world to avoid congestion 
  1782.    release_to_world( ATTACK_SQUAD_VEHICLES[attack_direction] ) 
  1783. end 
  1784.  
  1785. function ss08_member_do_attack( member_name ) 
  1786.    if ( character_is_released( member_name ) == false ) then 
  1787.       if ( character_is_dead( member_name ) == false ) then 
  1788.          if ( character_is_in_vehicle( member_name ) == true ) then 
  1789.             vehicle_exit( member_name ) 
  1790.          end 
  1791.          attack_closest_player( member_name ) 
  1792.       end 
  1793.    end 
  1794. end 
  1795.  
  1796. function ss08_entered_drug_truck( player_name, vehicle_name ) 
  1797.  
  1798. 	mission_debug( "switching to state MS_TRAVELING_TO_BASE from entered_drug_truck", 15 ) 
  1799.    ss08_switch_state( MS_TRAVELING_TO_BASE ) 
  1800. end 
  1801.  
  1802. function ss08_next_junkie_wave_attack() 
  1803.    -- Calculate the next attack directions. 
  1804.    Cur_attack_directions = ss08_get_next_attack_directions() 
  1805.  
  1806.    for index, direction in pairs( Cur_attack_directions ) do 
  1807.       ss08_attack_squad_spawn( direction ) 
  1808.  
  1809.       -- Set death tracking up 
  1810.       ss08_add_death_tracking( direction ) 
  1811.    end 
  1812.  
  1813.    for index, direction in pairs( Cur_attack_directions ) do 
  1814.       -- Have the squad come and attack 
  1815.       thread_new( "ss08_attack_squad_attack", direction ) 
  1816.    end 
  1817. end 
  1818.  
  1819. function ss08_get_next_attack_directions() 
  1820.    local attack_directions = {} 
  1821.  
  1822.    -- Waves up to a point should only come from one direction 
  1823.    if ( Num_junkie_attack_waves_defeated < 2 ) then 
  1824.       if ( Cur_attack_directions[1] == NUM_ATTACK_DIRECTIONS ) then 
  1825.          attack_directions[1] = 1 
  1826.       else 
  1827.          attack_directions[1] = Cur_attack_directions[1] + 1 
  1828.       end 
  1829.    -- Waves after the cutoff should come from two directions at once 
  1830.    else 
  1831.       -- Find a random direction 
  1832.       attack_directions[1] = (rand_int( 1, NUM_ATTACK_DIRECTIONS )) 
  1833.       -- Now, find another one that's different than the first 
  1834.       repeat 
  1835.          attack_directions[2] = (rand_int( 1, NUM_ATTACK_DIRECTIONS )) 
  1836.       until ( attack_directions[2] ~= attack_directions[1] ) 
  1837.    end 
  1838.  
  1839.    return attack_directions 
  1840. end 
  1841.  
  1842. function ss08_force_spawn_wave( wave_index_at_force_spawn ) 
  1843.    delay ( BELOW_MIN_ATTACKERS_FORCE_SPAWN_DELAY_SECONDS ) 
  1844.  
  1845.    local cur_wave_index = Num_junkie_attack_waves_defeated + 1 
  1846.  
  1847.    -- If the force-spawn situation no longer exists, abort. 
  1848.    if ( Cur_attackers_remaining >= MIN_ATTACKERS or 
  1849.         Cur_attackers_remaining == 0 or 
  1850.         -- Another wave has been spawned while we were waiting 
  1851.         cur_wave_index > wave_index_at_force_spawn or 
  1852.         Assault_turned_on == false ) then 
  1853.       return 
  1854.    end 
  1855.  
  1856.    -- For each currently attacking direction 
  1857.    for index, direction in pairs ( Cur_attack_directions ) do 
  1858.       release_to_world( ALL_ATTACK_SQUADS[direction] ) 
  1859.    end 
  1860.  
  1861.    Cur_attackers_remaining = 0 
  1862.    mission_debug( "Cur_attackers_remaining = "..Cur_attackers_remaining..".", 5 ) 
  1863.    Num_junkie_attack_waves_defeated = Num_junkie_attack_waves_defeated + 1 
  1864.    ss08_next_junkie_wave_attack() 
  1865. end 
  1866.  
  1867. function ss08_squad_member_died( member_name ) 
  1868.    if ( character_is_released( member_name ) == false ) then 
  1869.       release_to_world( member_name ) 
  1870.    end 
  1871.    Cur_attackers_remaining = Cur_attackers_remaining - 1 
  1872.    mission_debug( "Cur_attackers_remaining = "..Cur_attackers_remaining..".", 5 ) 
  1873.  
  1874.    --  
  1875.    if ( Cur_attackers_remaining < MIN_ATTACKERS ) then 
  1876.       Force_spawn_thread_handle = thread_new( "ss08_force_spawn_wave", Num_junkie_attack_waves_defeated + 1 ) 
  1877.    end 
  1878.  
  1879.    if ( Cur_attackers_remaining == 0 and Assault_turned_on == true ) then 
  1880.       Num_junkie_attack_waves_defeated = Num_junkie_attack_waves_defeated + 1 
  1881.       -- For each direction 
  1882.       for index, direction in pairs ( Cur_attack_directions ) do 
  1883.          release_to_world( ALL_ATTACK_SQUADS[direction] ) 
  1884.       end 
  1885.       ss08_next_junkie_wave_attack() 
  1886.    end 
  1887. end 
  1888.  
  1889. -- This function delays for a short time and then makes a callback, 
  1890. -- switching the mission state to the "Three Junkies attack" state. 
  1891. -- 
  1892. function ss08_before_attack_delay() 
  1893.    --action_play_non_blocking( character_name, anim_name, morph_name, force_play, stand_still ) 
  1894.    action_play_non_blocking( PIERCE_NAME, "talk disrespect", "", true, true ) 
  1895.    audio_play_conversation( PIERCE_COMPLAINING_DIALOG_STREAM, NOT_CALL ) 
  1896.  
  1897. 	mission_debug( "switching to state MS_INITIAL_JUNKIES_ATTACK from before_attack_delay", 15 ) 
  1898.    ss08_switch_state( MS_INITIAL_JUNKIES_ATTACK ) 
  1899. end 
  1900.  
  1901. -- Callback on death of the initial junkies that are spawned 
  1902. -- when the junkie attack starts. 
  1903. -- 
  1904. -- junkie_name: Name of the junkie that died. 
  1905. -- 
  1906. function ss08_initial_junkie_died( junkie_name ) 
  1907.    release_to_world( junkie_name ) 
  1908.    Initial_junkies_remaining = Initial_junkies_remaining - 1 
  1909.    if ( Initial_junkies_remaining == 3 ) then 
  1910. 		mission_debug( "switching to state MS_REAL_ATTACK_STARTS from initial_junkie_died", 15 ) 
  1911. 		ss08_switch_state( MS_REAL_ATTACK_STARTS ) 
  1912.    end 
  1913. end 
  1914.  
  1915. function ss08_cleanup() 
  1916.    -- Cleanup mission here 
  1917.    --for index, name in pairs( DRUG_BOXES ) do 
  1918.    --   mesh_mover_show( name ) 
  1919.    --end 
  1920.  
  1921.    -- Clean up any ambient junkies, since they may have been released to the world 
  1922.    spawning_pedestrians( false ) 
  1923.    spawning_pedestrians( true ) 
  1924.  
  1925.    ss08_add_vehicle_enter_and_exit_callbacks( "", "" ) 
  1926.    if ( Garage_door_open ) then 
  1927.       mesh_mover_play_action( GARAGE_DOOR, "start2" ) 
  1928.    end 
  1929.    on_dismiss( "", PIERCE_NAME ) 
  1930.    on_dismiss( "", SHAUNDI_NAME ) 
  1931.    on_death( "", PIERCE_NAME ) 
  1932.    on_death( "", SHAUNDI_NAME ) 
  1933.    on_tailing_too_far( "" ) 
  1934.    on_tailing_good( "" ) 
  1935.    on_vehicle_destroyed( "", DRUG_TRUCK ) 
  1936.    on_take_damage( "", DRUG_TRUCK ) 
  1937.    on_collision( "", DRUG_TRUCK ) 
  1938.    distance_display_off(SYNC_ALL) 
  1939.    hud_timer_stop( OBJECTIVE_TIME_INDEX) 
  1940.    hud_timer_hide( OBJECTIVE_TIME_INDEX, false ) 
  1941.    hud_timer_stop( FAILURE_TIME_INDEX ) 
  1942.    for index, name in pairs( CHASE_SQUAD_GROUP_NAMES ) do 
  1943.       local chase_trigger_name = CHASE_SQUAD_TRIGGER_NAMES[index] 
  1944.       trigger_enable( chase_trigger_name, false ) 
  1945.       on_trigger( "", chase_trigger_name ) 
  1946.    end 
  1947.    notoriety_force_no_spawn( POLICE_GANG, false ) 
  1948.  
  1949.    trigger_enable( WAREHOUSE_AREA, false ) 
  1950.    on_trigger( "", WAREHOUSE_AREA ) 
  1951.    on_trigger_exit( "", WAREHOUSE_AREA ) 
  1952.    -- Activate the final objective trigger 
  1953.    trigger_enable( SAINTS_HQ, false ) 
  1954.    on_trigger( "", SAINTS_HQ ) 
  1955.    set_dont_drop_havok_weapons_on_idle( false ) 
  1956.    party_allow_max_followers( false ) 
  1957.  
  1958.    if ( vehicle_exists( DRUG_TRUCK ) ) then 
  1959.       vehicle_door_prevent_damage_detach( DRUG_TRUCK, "Door_BR", false ) 
  1960.       vehicle_door_prevent_damage_detach( DRUG_TRUCK, "Door_BL", false ) 
  1961.    end 
  1962.  
  1963. 	parking_spot_enable( "parking_spots_$parking_341 (1)", true ) 
  1964. 	parking_spot_enable( "parking_spots_$parking_341 (0)", true ) 
  1965.  
  1966.    ss08_hide_doors( false ) 
  1967. end 
  1968.  
  1969. function ss08_success() 
  1970. 	-- Called when the mission has ended with success 
  1971. end 
  1972.