samedi 8 mars 2014

[Release] Multiple Team Ai improvments (Some of them are epic!) topic




Hello there Payday fanatics!
I almost always play Payday 2 for it's single player. And I was really mad to see there only be 2 team Ai bots instead of 3, Overkill made them only crouch (bug in patch 22, I fixed it) and other things. This thread will give you multiple codes for changing the Team Ai to make them better, faster, more health, you name it. I will update this thread with "new" codes and future updates as much as I can.
Feel free to request things/tweaks for the Team Ai and I will see if they are possible.


Most of these can be changed to your liking, while some can NOT be changed and may cause crashing, bugs, etc.

Some of these options may become outdated as future patches/updates come out. I will keep this thread up to date whenever something is changed and/or broken.

I want to give a HUGE thanks to v00d00 for the decompiled source code for multiple patches or else this wouldn't have been possible, and for the massive amount of help he has given me. I also want to thank Pirate Captain for helping me with questions, and even adding my 3 Team Ai script to his V12 of Pirate Perfection.
So here are the codes/scripts:
The below codes are fully changeable.


Code:



 -- TEAM MEMBERS
tweak_data.character.presets.gang_member_damage.REGENERATE_TIME = 0.2        -- Amount of time to pass before regenerate
tweak_data.character.presets.gang_member_damage.REGENERATE_TIME_AWAY = 0.1      -- Amount of time to pass before regenerate when this criminal is far away from players
tweak_data.character.presets.gang_member_damage.HEALTH_INIT = 365  --Amount of health Team Ai have before getting downed.  (Default is 75)
tweak_data.character.presets.gang_member_damage.DOWNED_TIME = 41 --(Amount of time in down until "dead", default is 30)
 tweak_data.character.presets.gang_member_damage.ARRESTED_TIME = 20    -- Amount of time in arrest before "dead" (Default is 60)
tweak_data.character.presets.gang_member_damage.INCAPACITATED_TIME = 41 --(Amount of time in down until "dead", default is 30)


The below code changes the Team Ai movement speed from fast, to lightning (lightning is the move speed that ONLY Cloakers use) Also so you know, the Team Ai in some settings are called "gang_member" and in other settings named by there game files names. ex. Russian=Dallas, German= Wolf, American=Hoxton, and Spanish=Chains.


Code:



 tweak_data.character.russian.move_speed = tweak_data.character.presets.move_speed.lightning
tweak_data.character.german.move_speed = tweak_data.character.presets.move_speed.lightning
tweak_data.character.spanish.move_speed = tweak_data.character.presets.move_speed.lightning
tweak_data.character.american.move_speed = tweak_data.character.presets.move_speed.lightning


The below code is one of the things a lot of people have been asking me how to do/change, so I figured it's time to give you the code. This is, how to change the Team Ai's weapons!Completely changeable


Code:


--Atempting to change gang member weapons
tweak_data.character.russian.weapon.weapons_of_choice = {
primary = Idstring( "units/payday2/weapons/wpn_npc_lmg_m249/wpn_npc_lmg_m249" ), --Always use! Unless getting tired of it then put him with the G36 instead!
--primary = Idstring( "units/payday2/weapons/wpn_npc_s552/wpn_npc_s552" ), --Not in the game....YET...
--primary = Idstring( "units/payday2/weapons/wpn_npc_mp5_tactical/wpn_npc_mp5_tactical" )
--primary = Idstring( "units/payday2/weapons/wpn_npc_mp5/wpn_npc_mp5" ),
secondary = Idstring( "units/payday2/weapons/wpn_npc_mac11/wpn_npc_mac11" )
--secondary = Idstring( "units/payday2/weapons/wpn_npc_c45/wpn_npc_c45" )
}

tweak_data.character.german.weapon.weapons_of_choice = {
primary = Idstring( "units/payday2/weapons/wpn_npc_mp5/wpn_npc_mp5" ),
--secondary = Idstring( "units/payday2/weapons/wpn_npc_beretta92/wpn_npc_beretta92" )
}

tweak_data.character.american.weapon.weapons_of_choice = {
primary = Idstring( "units/payday2/weapons/wpn_npc_ump/wpn_npc_ump" )
--primary = Idstring( "units/payday2/weapons/wpn_npc_g36/wpn_npc_g36" ),
--primary = Idstring( "units/payday2/weapons/wpn_npc_m4/wpn_npc_m4" ),
--primary = Idstring( "units/payday2/weapons/wpn_npc_sawnoff_shotgun/wpn_npc_sawnoff_shotgun" ),
--secondary = Idstring( "units/payday2/weapons/wpn_npc_mac11/wpn_npc_mac11" )
--secondary = Idstring( "units/payday2/weapons/wpn_npc_mp5_tactical/wpn_npc_mp5_tactical" )
--secondary = Idstring( "units/payday2/weapons/wpn_npc_raging_bull/wpn_npc_raging_bull" )
}

tweak_data.character.spanish.weapon = deep_clone( tweak_data.character.presets.weapon.gang_member )
tweak_data.character.spanish.weapon.r870.FALLOFF[1].dmg_mul = 7.5
tweak_data.character.spanish.weapon.r870.FALLOFF[2].dmg_mul = 6.5
tweak_data.character.spanish.weapon.r870.FALLOFF[3].dmg_mul = 5.5
tweak_data.character.spanish.weapon.r870.RELOAD_SPEED = 1
tweak_data.character.spanish.weapon.weapons_of_choice = {
primary = Idstring( "units/payday2/weapons/wpn_npc_r870/wpn_npc_r870" ),
--primary = Idstring( "units/payday2/weapons/wpn_npc_benelli/wpn_npc_benelli" ), --For some reason I have NEVER seen the gensec elite shotgun guy yet, still waitinbg on source code to find out more.
--primary = Idstring( "units/payday2/weapons/wpn_npc_g36/wpn_npc_g36" ),
--primary = Idstring( "units/payday2/weapons/wpn_npc_ak47/wpn_npc_ak47" ),
secondary = Idstring( "units/payday2/weapons/wpn_npc_raging_bull/wpn_npc_raging_bull" )
--secondary = Idstring( "units/payday2/weapons/wpn_npc_mac11/wpn_npc_mac11" )
}


Below is a list giving you all the possible npc weapons they can use. Remember, NPC's can NOT use all the weapons we can use, because there is no model for them, etc.


Code:



 
 self.weap_unit_names = {
  Idstring( "units/payday2/weapons/wpn_npc_beretta92/wpn_npc_beretta92" ),
  Idstring( "units/payday2/weapons/wpn_npc_c45/wpn_npc_c45" ),
  Idstring( "units/payday2/weapons/wpn_npc_raging_bull/wpn_npc_raging_bull" ),
  Idstring( "units/payday2/weapons/wpn_npc_m4/wpn_npc_m4" ),
  Idstring( "units/payday2/weapons/wpn_npc_ak47/wpn_npc_ak47" ),
  Idstring( "units/payday2/weapons/wpn_npc_r870/wpn_npc_r870" ),
  Idstring( "units/payday2/weapons/wpn_npc_sawnoff_shotgun/wpn_npc_sawnoff_shotgun" ), --this one surprisingly actually DOES work with the Team Ai.  It's actually currently NOT being used by any enemies in the game either.  Maybe they scrapped it and just kept the model and everything in the files for reference?
  Idstring( "units/payday2/weapons/wpn_npc_mp5/wpn_npc_mp5" ),
  Idstring( "units/payday2/weapons/wpn_npc_mp5_tactical/wpn_npc_mp5_tactical" ),
  Idstring( "units/payday2/weapons/wpn_npc_smg_mp9/wpn_npc_smg_mp9" ), --Have NOT tested this one, so not sure if it will work or not.
  Idstring( "units/payday2/weapons/wpn_npc_mac11/wpn_npc_mac11" ),
  Idstring( "units/payday2/weapons/wpn_npc_sniper/wpn_npc_sniper" ), --does NOT work, will cause crash.
  Idstring( "units/payday2/weapons/wpn_npc_saiga/wpn_npc_saiga" ), --does NOT work.
 Idstring( "units/payday2/weapons/wpn_npc_lmg_m249/wpn_npc_lmg_m249" )  --Actually works.  Packs quite a punch to.
 Idstring( "units/payday2/weapons/wpn_npc_s552/wpn_npc_s552" ) --NOT IN THE GAME YET!
 Idstring( "units/payday2/weapons/wpn_npc_ump/wpn_npc_ump" )
Idstring( "units/payday2/weapons/wpn_npc_g36/wpn_npc_g36" )


I have put a note beside the weapons that will NOT work with the Team Ai, so don't even attempt to use them, because they will just crash your game.


The following is something I think A LOT of you are going to enjoy. ;) It makes the Team Ai...BE ABLE TO DODGE! Just like the cops do! But I made it so that they only do the side_step, because the dive dodge is useless, and takes to long. I am working on adding in the roll dodge, but not ready yet. Completely changeable.


Code:



 tweak_data.character.russian.dodge = tweak_data.character.presets.dodge.athletic
tweak_data.character.spanish.dodge = tweak_data.character.presets.dodge.athletic
tweak_data.character.american.dodge = tweak_data.character.presets.dodge.athletic
 tweak_data.character.german.dodge = tweak_data.character.presets.dodge.athletic


The below code makes the Team Ai get cuffed instead of downed whenever a Cloaker attacks them (Just like in PDTH)


Code:



 function TeamAIMovement:on_SPOOCed()
 self._unit:brain():set_logic( "surrender" )
 self._unit:network():send( "arrested" )
 self._unit:character_damage():on_arrested()
end


The below code makes the Player (only you, not other players) get cuffed instead of being downed, whenever a cloaker attacks them.


Code:



 function PlayerMovement:on_SPOOCed()
 if self._unit:character_damage()._god_mode then
  return
 end
  if self._current_state_name == "standard" or self._current_state_name == "bleed_out" then
  managers.player:set_player_state( "arrested" )
 end
end



The below code makes it so that there are 3 Team Ai instead of the default 2. Can even be changed to only have 1 team ai. No more then 3 of course.


Code:



 CriminalsManager = CriminalsManager or class()
 CriminalsManager.MAX_NR_TEAM_AI = 3
 function CriminalsManager:init()
 self._characters =
 {
  -- Hoxton
  { taken = false, name = "american", unit = nil, peer_id = 0, static_data = { ai_character_id = "ai_hoxton", ssuffix = "d", color_id = 1, voice = "rb2", ai_mask_id = "hoxton", mask_id = 1 }, data = {} },
 
  -- Wolf
  { taken = false, name = "german",  unit = nil, peer_id = 0, static_data = { ai_character_id = "ai_wolf", ssuffix = "c", color_id = 2, voice = "rb3", ai_mask_id = "wolf", mask_id = 2 }, data = {} },
 
  -- Dallas
  { taken = false, name = "russian",  unit = nil, peer_id = 0, static_data = { ai_character_id = "ai_dallas", ssuffix = "a", color_id = 3, voice = "rb4", ai_mask_id = "dallas", mask_id = 3 }, data = {} },
 
  -- Chains
  { taken = false, name = "spanish",  unit = nil, peer_id = 0, static_data = { ai_character_id = "ai_chains", ssuffix = "b", color_id = 4, voice = "rb1", ai_mask_id = "chains", mask_id = 4 }, data = {} }
 }
end
 -----------------------------------------------------------------------------------
 function CriminalsManager.convert_old_to_new_character_workname( workname )
 local t = { american = "hoxton", german = "wolf", russian = "dallas", spanish = "chains" }
 return t[ workname ]
end
 function CriminalsManager.character_names()
 return { "russian", "german", "spanish", "american" }
end
 function CriminalsManager.character_workname_by_peer_id( peer_id )
 local t = { "russian", "german", "spanish", "american" }
 return t[ peer_id ]
end
 function CriminalsManager:on_simulation_ended()
 for id, data in pairs( self._characters ) do
  self:_remove( id )
 end
end
 -----------------------------------------------------------------------------------
 function CriminalsManager:local_character_name()
 return self._local_character
end
 function CriminalsManager:characters()
 return self._characters
end
 -----------------------------------------------------------------------------------
 function CriminalsManager:get_any_unit()
 for id, data in pairs( self._characters ) do
  if data.taken and alive( data.unit ) and data.unit:id() ~= -1 then
  return data.unit
  end
 end
end
 -----------------------------------------------------------------------------------
 function CriminalsManager:_remove( id )
 local data = self._characters[ id ]
 
 print("[CriminalsManager:_remove]", inspect( data ) )
 
 if data.name == self._local_character then
  self._local_character = nil
 end
  if data.unit then
--  managers.hud:remove_hud_info_by_unit( data.unit )
  managers.hud:remove_mugshot_by_character_name( data.name )
 else
  managers.hud:remove_teammate_panel_by_name_id( data.name )
 end
  data.taken = false
 data.unit = nil
 data.peer_id = 0
 data.data = {}
end
 -----------------------------------------------------------------------------------
 function CriminalsManager:add_character( name, unit, peer_id, ai )
 print("[CriminalsManager:add_character]", name, unit, peer_id, ai)
 Application:stack_dump()
 
 if unit then
  unit:base()._tweak_table = name
 end
 
 for id, data in pairs( self._characters ) do
  if data.name == name then
  if data.taken then
    Application:error( "[CriminalsManager:set_character] Error: Trying to take a unit slot that has already been taken!" )
    Application:stack_dump()
    Application:error( "[CriminalsManager:set_character] -----" )
   
    self:_remove( id )
  end
 
  data.taken = true
  data.unit = unit
  data.peer_id = peer_id
  data.data.ai = ai or false
    -- local mask_set = Global.game_settings.single_player and managers.network:session():local_peer():mask_set() or ((not ai) and managers.network:session():peer( peer_id ):mask_set() or "clowns")
  -- local set = tweak_data.mask_sets[ mask_set ][ data.static_data.mask_id ]
 
  data.data.mask_obj = tweak_data.blackmarket.masks[ data.static_data.ai_mask_id ].unit -- set.mask_obj
  -- data.data.mask_icon = set.mask_icon
  data.data.mask_id = nil
  data.data.mask_blueprint = nil
 
  if not ai and unit then
    local mask_id = managers.network:session():peer( peer_id ):mask_id()
    data.data.mask_obj = managers.blackmarket:mask_unit_name_by_mask_id( mask_id, peer_id ) -- tweak_data.blackmarket.masks[ mask_id ].unit
    data.data.mask_id = mask_id
    data.data.mask_blueprint = managers.network:session():peer( peer_id ):mask_blueprint()
  end
 
  managers.hud:remove_mugshot_by_character_name( name )
  if unit then
    data.data.mugshot_id = managers.hud:add_mugshot_by_unit( unit )
    if unit:base().is_local_player then
    self._local_character = name
    managers.hud:reset_player_hpbar()
    end
   
    unit:sound():set_voice( data.static_data.voice )
    unit:inventory():set_mask_visibility( unit:inventory()._mask_visibility )
  else
    data.data.mugshot_id = managers.hud:add_mugshot_without_unit( name, ai, peer_id,
    ai and managers.localization:text( "menu_"..name ) or managers.network:session():peer( peer_id ):name() )
  end
  break
  end
 end
 --print( "exited ok" )
end
 -----------------------------------------------------------------------------------
 function CriminalsManager:set_unit( name, unit )
 print("[CriminalsManager:set_unit] name", name, "unit", unit )
 Application:stack_dump()
 
 unit:base()._tweak_table = name
  for id, data in pairs( self._characters ) do
  if data.name == name then
  if not data.taken then
    Application:error( "[CriminalsManager:set_character] Error: Trying to set a unit on a slot that has not been taken!" )
    Application:stack_dump()
    return
  end
  --[[
  if data.unit then
    managers.hud:remove_hud_info_by_unit( data.unit )
  end
  ]]
  data.unit = unit
 
  managers.hud:remove_mugshot_by_character_name( data.name )
  data.data.mugshot_id = managers.hud:add_mugshot_by_unit( unit )
 
  data.data.mask_obj = tweak_data.blackmarket.masks[ data.static_data.ai_mask_id ].unit -- set.mask_obj
  -- data.data.mask_icon = set.mask_icon
  data.data.mask_id = nil
  data.data.mask_blueprint = nil
 
  if not data.data.ai then
    local mask_id = managers.network:session():peer( data.peer_id ):mask_id()
    data.data.mask_obj = managers.blackmarket:mask_unit_name_by_mask_id( mask_id, data.peer_id ) -- tweak_data.blackmarket.masks[ mask_id ].unit
    data.data.mask_id = mask_id
    data.data.mask_blueprint = managers.network:session():peer( data.peer_id ):mask_blueprint()
  end
   
  if unit:base().is_local_player then
    self._local_character = name
    managers.hud:reset_player_hpbar()
  end
 
  unit:sound():set_voice( data.static_data.voice )
 
  break
  end
 end
 --print( "exited ok" )
end
 -----------------------------------------------------------------------------------
 function CriminalsManager:is_taken( name )
 for _, data in pairs( self._characters ) do
  if name == data.name then
  return data.taken
  end
 end
 
 return false
end
 -----------------------------------------------------------------------------------
 function CriminalsManager:character_name_by_peer_id( peer_id )
 for _, data in pairs( self._characters ) do
  if data.taken and peer_id == data.peer_id then
  return data.name
  end
 end
end
 -----------------------------------------------------------------------------------
 function CriminalsManager:character_color_id_by_peer_id( peer_id )
 local workname = self.character_workname_by_peer_id( peer_id )
 return self:character_color_id_by_name( workname )
 --[[for _, data in pairs( self._characters ) do
  if data.taken and peer_id == data.peer_id then
  return data.static_data.color_id
  end
 end]]
end
 -----------------------------------------------------------------------------------
 function CriminalsManager:character_color_id_by_unit( unit )
 local search_key = unit:key()
 for id, data in pairs( self._characters ) do
  if data.unit and data.taken and search_key == data.unit:key() then
  if data.data.ai then
    return 5
  end
  return data.peer_id -- self:character_color_id_by_peer_id( data.peer_id )
  -- local workname = managers.criminals:character_workname_by_peer_id( data.peer_id )
  -- return self:character_color_id_by_name( workname )
  -- return data.static_data.color_id
  end
 end
end
 function CriminalsManager:character_color_id_by_name( name )
 --[[for i,c_name in ipairs( self:character_names() ) do
  if c_name == name then
  return i
  -- return self:character_color_id_by_peer_id( i )
  end
 end]]
 for id, data in pairs( self._characters ) do
  if name == data.name then
  -- return self:character_color_id_by_peer_id( data.peer_id )
  return data.static_data.color_id
  end
 end
end
 -----------------------------------------------------------------------------------
 function CriminalsManager:character_data_by_name( name )
 for _, data in pairs( self._characters ) do
  if data.taken and name == data.name then
  return data.data
  end
 end
end
 -----------------------------------------------------------------------------------
 function CriminalsManager:character_data_by_peer_id( peer_id )
 for _, data in pairs( self._characters ) do
  if data.taken and peer_id == data.peer_id then
  return data.data
  end
 end
end
 -----------------------------------------------------------------------------------
 function CriminalsManager:character_data_by_unit( unit )
 local search_key = unit:key()
 for id, data in pairs( self._characters ) do
  if data.unit and data.taken and search_key == data.unit:key() then
  return data.data
  end
 end
end
 -----------------------------------------------------------------------------------
 function CriminalsManager:character_static_data_by_name( name )
 for _, data in pairs( self._characters ) do
  if name == data.name then
  return data.static_data
  end
 end
end
 -----------------------------------------------------------------------------------
 function CriminalsManager:character_unit_by_name( name )
 for _, data in pairs( self._characters ) do
  if data.taken and name == data.name then
  return data.unit
  end
 end
end
 -----------------------------------------------------------------------------------
 function CriminalsManager:character_taken_by_name( name )
 for _, data in pairs( self._characters ) do
  if name == data.name then
  return data.taken
  end
 end
end
-----------------------------------------------------------------------------------
 function CriminalsManager:character_peer_id_by_name( name )
 for _, data in pairs( self._characters ) do
  if data.taken and name == data.name then
  return data.peer_id
  end
 end
end
 -----------------------------------------------------------------------------------
 function CriminalsManager:get_free_character_name()
 local available = {}
  for id, data in pairs( self._characters ) do
  local taken = data.taken
 
  if not taken then
  for _, member in pairs(managers.network:game():all_members()) do
    if member._assigned_name == data.name then
    taken = true
    break
    end
  end
  end
 
  if not taken then
  table.insert( available, data.name )
  end
 end
 
 if #available > 0 then
  return available[ math.random(#available) ]
 end
end
 -----------------------------------------------------------------------------------
 function CriminalsManager:get_num_player_criminals()
 local num = 0
 for id, data in pairs( self._characters ) do
  if data.taken and not data.data.ai then
  num = num + 1
  end
 end
 
 return num
end
 -----------------------------------------------------------------------------------
 function CriminalsManager:remove_character_by_unit( unit )
 if type_name( unit ) ~= "Unit" then
  return
 end
  local rem_u_key = unit:key()
 for id, data in pairs( self._characters ) do
  if data.unit and data.taken and rem_u_key == data.unit:key() then
  self:_remove( id )
  return
  end
 end
end
 -----------------------------------------------------------------------------------
 function CriminalsManager:remove_character_by_peer_id( peer_id )
 for id, data in pairs( self._characters ) do
  if data.taken and peer_id == data.peer_id then
  self:_remove( id )
  return
  end
 end
end
 -----------------------------------------------------------------------------------
 function CriminalsManager:remove_character_by_name( name )
 for id, data in pairs( self._characters ) do
  if data.taken and name == data.name then
  self:_remove( id )
  return
  end
 end
end
 -----------------------------------------------------------------------------------
 function CriminalsManager:character_name_by_unit( unit )
 if type_name( unit ) ~= "Unit" then
  return nil
 end
 local search_key = unit:key()
 for id, data in pairs( self._characters ) do
  if data.unit and data.taken and search_key == data.unit:key() then
  return data.name
  end
 end
end
 -----------------------------------------------------------------------------------
 function CriminalsManager:character_name_by_panel_id( panel_id )
 for id, data in pairs( self._characters ) do
  if data.taken and data.data.panel_id == panel_id then
  return data.name
  end
 end
end
 -----------------------------------------------------------------------------------
 function CriminalsManager:character_static_data_by_unit( unit )
 if type_name( unit ) ~= "Unit" then
  return nil
 end
 local search_key = unit:key()
 for id, data in pairs( self._characters ) do
  if data.unit and data.taken and search_key == data.unit:key() then
  return data.static_data
  end
 end
end
 -----------------------------------------------------------------------------------
 function CriminalsManager:nr_AI_criminals()
 local nr_AI_criminals = 0
 for i, char_data in pairs( self._characters ) do
  if char_data.data.ai then
  nr_AI_criminals = nr_AI_criminals + 1
  end
 end
 return nr_AI_criminals
end



The following fixes the Team Ai crouch bug, where the Team Ai can only move while crouching (started in patch 22 infamy, and still not fixed by Overkill)Completely changeable


Code:



 function TeamAILogicTravel.update( data )
 local unit = data.unit
 local objective = data.objective
 
 if not objective then
  TeamAILogicIdle.on_new_objective( data, nil )
  return
 end
 
 local my_data = data.internal_data
 local t = data.t
 
 if my_data.processing_advance_path or my_data.processing_coarse_path then
  TeamAILogicTravel._upd_pathing( data, my_data )
  if my_data ~= data.internal_data then
  return
  end
 elseif my_data.advancing then
  if data.objective.type == "follow" then
  if (not unit:movement():chk_action_forbidden("walk") or unit:anim_data().act_idle) then
    local follow_unit_nav_seg = data.objective.follow_unit:movement():nav_tracker():nav_segment()
    if follow_unit_nav_seg ~= my_data.coarse_path[ my_data.coarse_path_index + 1 ][1] or my_data.coarse_path_index ~= #my_data.coarse_path - 1 then -- we are not moving to the follow_unit's nav_segment
    local my_nav_seg = data.unit:movement():nav_tracker():nav_segment()
    if follow_unit_nav_seg == my_nav_seg then
      --debug_pause_unit( data.unit, "Im next to my follow unit. STOP! follow_unit_nav_seg", follow_unit_nav_seg, "my_data.coarse_path", inspect( my_data.coarse_path ), "my_data.coarse_path_index", my_data.coarse_path_index )
      objective.in_place = true -- we have reached the objective area
      TeamAILogicTravel.on_new_objective( data ) -- re-evaluate our objective
      return
    end
    end
  end
  end
 elseif my_data.cover_leave_t then -- waiting in cover
  if not my_data.turning and (not unit:movement():chk_action_forbidden("walk") or not (not unit:anim_data().act_idle)) then
  if t > my_data.cover_leave_t then
    my_data.cover_leave_t = nil
  elseif my_data.best_cover then
    local action_taken
    if not unit:movement():attention() then
    action_taken = CopLogicTravel._chk_request_action_turn_to_cover( data, my_data )
    end
    if not action_taken then
    if not ( my_data.best_cover[4] or unit:anim_data().crouch or data.unit:movement():cool() ) then
      CopLogicAttack._chk_request_action_stand( data )
    end
    end
  end
  end
 elseif my_data.advance_path then
  if (not unit:movement():chk_action_forbidden("walk") or unit:anim_data().act_idle) then
  local haste, no_strafe
  if objective and objective.haste then
    haste = objective.haste
  elseif unit:movement():cool() then
    haste = "walk"
  else
    haste = "run"
  end
 
  CopLogicTravel._chk_request_action_walk_to_advance_pos( data, my_data, haste, objective and objective.rot, no_strafe )
  if my_data.advancing then
    TeamAILogicTravel._check_start_path_ahead( data )
  end
  end
 elseif objective then
  if my_data.coarse_path then
  local coarse_path = my_data.coarse_path
  local cur_index = my_data.coarse_path_index
  local total_nav_points = #coarse_path
  if cur_index == total_nav_points then  -- We have reached the final nav point. The area is investigated.
    objective.in_place = true -- we have reached the objective area
    if objective.type == "investigate_area" or objective.type == "free" then
    if not objective.action_duration then
      managers.groupai:state():on_criminal_objective_complete( unit, objective )
      return
    end
    end
    TeamAILogicTravel.on_new_objective( data ) -- re-evaluate our objective
    return
  else
    local to_pos = TeamAILogicTravel._get_exact_move_pos( data, cur_index + 1 )
    my_data.advance_path_search_id = tostring( data.key ).."advance"
    my_data.processing_advance_path = true
    local prio
    if objective and objective.follow_unit then
    prio = 5
    end
    local nav_segs = CopLogicTravel._get_allowed_travel_nav_segs( data, my_data, to_pos )
    --[[my_data._search_nav_segs = nav_segs
    my_data._path_trail = { mvector3.copy(data.m_pos), mvector3.copy(to_pos) }
    my_data._path_tag = "next"]]
    unit:brain():search_for_path( my_data.advance_path_search_id, to_pos, prio, nil, nav_segs )
  end
  else
  local search_id = tostring( unit:key() ).."coarse"
  local nav_seg
  if objective.follow_unit then
    nav_seg = objective.follow_unit:movement():nav_tracker():nav_segment()
  else
    nav_seg = objective.nav_seg
  end
  if unit:brain():search_for_coarse_path( search_id, nav_seg ) then
    my_data.coarse_path_search_id = search_id
    my_data.processing_coarse_path = true
  end
  end
 else
  CopLogicBase._exit( data.unit, "idle", { scan = true } )
  return
 end
  local action_taken = data.unit:movement():chk_action_forbidden("walk") and not unit:anim_data().act_idle
 local want_to_take_cover = TeamAILogicTravel._chk_wants_to_take_cover( data, my_data )
 
 -- Check if we should crouch or stand
 if not action_taken then
  if want_to_take_cover or data.char_tweak.no_stand then  -- I do not have cover or my cover is low and I am not crouched
  if not unit:anim_data().crouch then
    action_taken = CopLogicAttack._chk_request_action_crouch( data )  --Is bugged with Stand, testing with stand, but probably will have to just use crouch.  Has bugged animations with stand.
  end
  elseif unit:anim_data().crouch then
  if not data.char_tweak.allow_crouch then
    action_taken = CopLogicAttack._chk_request_action_stand( data )
  end
  end
 end
end
 -----------------------------------------------------------------------------
 function TeamAILogicAssault.update( data )
 local my_data = data.internal_data
 local t = data.t
 local unit = data.unit
 local focus_enemy = data.attention_obj
 local in_cover = my_data.in_cover
 local best_cover = my_data.best_cover
 
 CopLogicAttack._process_pathing_results( data, my_data )
 
 local focus_enemy = data.attention_obj
 if not focus_enemy or focus_enemy.reaction < AIAttentionObject.REACT_AIM then
  TeamAILogicAssault._upd_enemy_detection( data, true ) -- second param means it is not called as a queued task
  if my_data ~= data.internal_data or not data.attention_obj or data.attention_obj.reaction <= AIAttentionObject.REACT_SCARED then
  return
  end
  focus_enemy = data.attention_obj -- we found an enemy
 end
 
 local enemy_visible = focus_enemy.verified
 
 local action_taken = my_data.turning or data.unit:movement():chk_action_forbidden( "walk" ) or my_data.moving_to_cover or my_data.walking_to_cover_shoot_pos or my_data._turning_to_intimidate
 
 my_data.want_to_take_cover = CopLogicAttack._chk_wants_to_take_cover( data, my_data ) -- out of ammo, suppressed etc
 local want_to_take_cover = my_data.want_to_take_cover
 
 if not action_taken then
  if want_to_take_cover and ( not in_cover or not in_cover[4] ) or data.char_tweak.no_stand then  -- I do not have cover or my cover is low and I am not crouched
  if not unit:anim_data().crouch then
    action_taken = CopLogicAttack._chk_request_action_stand( data )
  end
  elseif unit:anim_data().crouch then
  if not data.char_tweak.allow_crouch or my_data.cover_test_step > 2 then
    action_taken = CopLogicAttack._chk_request_action_stand( data )
  end
  end
 end
 
 local move_to_cover
 
 if action_taken then
 elseif want_to_take_cover then -- we don't want trouble
  move_to_cover = true
 end
 --[[if not enemy_visible then
  if not action_taken then
  if my_data.in_cover then
    if my_data.attitude == "engage" then -- I want to get back into action
    local shoot_from_pos
    if not my_data.sideways_chk_t or t > my_data.sideways_chk_t then
      local my_tracker = unit:movement():nav_tracker()
      my_data.cover_test_step = my_data.cover_test_step or 1
      shoot_from_pos = CopLogicAttack._peek_for_pos_sideways( data, my_data, my_tracker, focus_enemy.m_pos, 160 )
      if my_data.cover_test_step > 2 then
      my_data.cover_test_step = 1
      else
      my_data.cover_test_step = my_data.cover_test_step + 1
      end
      my_data.sideways_chk_t = t + 1
    end
    if shoot_from_pos then
      local my_tracker = unit:movement():nav_tracker()
      local path = { my_tracker:position(), shoot_from_pos }
      CopLogicAttack._chk_request_action_walk_to_cover_shoot_pos( data, my_data, path )
    end
    end
  elseif not ( my_data.in_cover[4] or unit:anim_data().crouch ) then
    --print( "I am behind a low cover and not crouching. Crouch" )
    CopLogicAttack._chk_request_action_crouch( data )
  end
  end
 end]]
 
 if not ( my_data.processing_cover_path or my_data.cover_path or my_data.charge_path_search_id or action_taken )
  and best_cover
  and ( not in_cover or best_cover[1] ~= in_cover[1] )
 then
  CopLogicAttack._cancel_cover_pathing( data, my_data )
  local search_id = tostring( unit:key() ).."cover"
  if data.unit:brain():search_for_path_to_cover( search_id, best_cover[1], best_cover[5] ) then
  my_data.cover_path_search_id = search_id
  my_data.processing_cover_path = best_cover
  end
 end
 
 if not action_taken and move_to_cover and my_data.cover_path then
  action_taken = CopLogicAttack._chk_request_action_walk_to_cover( data, my_data )
 end
 
 if not data.objective and ( not data.path_fail_t or data.t - data.path_fail_t > 6 ) then
  managers.groupai:state():on_criminal_jobless( unit )
  if my_data ~= data.internal_data then
  return
  end
 end
 
 if data.t > my_data.cover_chk_t then
  CopLogicAttack._update_cover( data )
  my_data.cover_chk_t = data.t + TeamAILogicAssault._COVER_CHK_INTERVAL
 end
end


That's it for now! Hope you enjoy! Please leave comments below!
Droidaka,
UC Forum Moderator





Aucun commentaire:

Enregistrer un commentaire