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.
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.
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
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.
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.
The below code makes the Team Ai get cuffed instead of downed whenever a Cloaker attacks them (Just like in PDTH)
The below code makes the Player (only you, not other players) get cuffed instead of being downed, whenever a cloaker attacks them.

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.

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
That's it for now! Hope you enjoy! Please leave comments below!
Droidaka,
UC Forum Moderator
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.
Most of these can be changed to your liking, while some can NOT be changed and may cause crashing, bugs, etc.
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)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.lightningCode:
--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" )
}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" )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.athleticCode:
function TeamAIMovement:on_SPOOCed()
self._unit:brain():set_logic( "surrender" )
self._unit:network():send( "arrested" )
self._unit:character_damage():on_arrested()
endCode:
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
endThe 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
endThe 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
endDroidaka,
UC Forum Moderator
Aucun commentaire:
Enregistrer un commentaire