468 lines
18 KiB
Plaintext
468 lines
18 KiB
Plaintext
|
---- AI Additions ----
|
|||
|
---- Rulix aka Bak ----
|
|||
|
---- 27.07.2016
|
|||
|
|
|||
|
function printf(s, ...)
|
|||
|
-- rx_utils.printf("com:"..s,...)
|
|||
|
end
|
|||
|
|
|||
|
ASSERTX(rx_ai.rx_ini:section_exist("combat"),"no section [combat] in rx_ini")
|
|||
|
local run_on_hit = rx_utils.read_from_ini(rx_ai.rx_ini,"combat","run_on_hit",false,0)
|
|||
|
|
|||
|
--local set_inertia_time_5_10,set_inertia_time_15
|
|||
|
|
|||
|
local md_enabled = rx_utils.read_from_ini(rx_ai.rx_ini,"combat","monster_defend",false,0)
|
|||
|
local md_max_dist = 12*12
|
|||
|
local md_walk_dist = 9*9
|
|||
|
local md_run_dist = 5*5
|
|||
|
local md_min_rank = 0.2/rx_utils.rank_unit
|
|||
|
local md_monsters = {
|
|||
|
-- actor = 0,
|
|||
|
-- stalker = 0,
|
|||
|
bloodsucker = math.pi*0.3,
|
|||
|
boar = 0,
|
|||
|
burer = 0,
|
|||
|
cat = 0,
|
|||
|
chimera = math.pi*0.1,
|
|||
|
-- controller = 0,
|
|||
|
dog = math.pi*0.2,
|
|||
|
flesh = 0,
|
|||
|
fracture = 0,
|
|||
|
giant = 0,
|
|||
|
-- poltergeist = 0,
|
|||
|
pseudodog = 0,
|
|||
|
psy_dog = math.pi*0.8,
|
|||
|
psy_dog_phantom = 0,
|
|||
|
snork = math.pi*0.1,
|
|||
|
tushkano = 0,
|
|||
|
zombie = 0,
|
|||
|
}
|
|||
|
|
|||
|
local t = {}
|
|||
|
for name,cls_id in pairs(rx_utils.creatures_clslist) do
|
|||
|
t[cls_id] = md_monsters[name] or nil
|
|||
|
end
|
|||
|
md_monsters = t
|
|||
|
t = nil
|
|||
|
|
|||
|
local function suitable_target(npc,target)
|
|||
|
return target:alive() and md_monsters[target:clsid()] and npc:position():distance_to_sqr(target:position()) < md_max_dist --npc:max_ignore_monster_distance()
|
|||
|
end
|
|||
|
|
|||
|
class "evaluator_monster_defend" (property_evaluator)
|
|||
|
function evaluator_monster_defend:__init(npc,storage,name) super (nil,name)
|
|||
|
self.st = storage
|
|||
|
self.st.check_time = 0
|
|||
|
rx_ai.subscribe_for_events(npc,self)
|
|||
|
end
|
|||
|
function evaluator_monster_defend:evaluate()
|
|||
|
local npc = self.object
|
|||
|
-- if npc:critically_wounded() then
|
|||
|
-- return false
|
|||
|
-- end
|
|||
|
local be = npc:best_enemy()
|
|||
|
if not (be and npc:best_weapon()) then
|
|||
|
return false
|
|||
|
end
|
|||
|
local target = self.st.target and (db.storage[self.st.target] and db.storage[self.st.target].object or level.object_by_id(self.st.target))
|
|||
|
if target and suitable_target(npc,target) and (npc:see(target) or target:see(npc)) then
|
|||
|
return true
|
|||
|
else
|
|||
|
self.st.target = nil
|
|||
|
end
|
|||
|
if self.st.check_time > time_global() then
|
|||
|
return false
|
|||
|
end
|
|||
|
self.st.check_time = time_global()+700
|
|||
|
if npc:see(be) and suitable_target(npc,be) then
|
|||
|
self.st.target = be:id()
|
|||
|
return true
|
|||
|
end
|
|||
|
return false
|
|||
|
end
|
|||
|
function evaluator_monster_defend:hit_callback(amount,_,who)
|
|||
|
local npc = self.object
|
|||
|
if who and amount > 2 and suitable_target(npc,who) then
|
|||
|
self.st.target = who:id()
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
class "action_monster_defend" (planner_action)
|
|||
|
function action_monster_defend:__init (npc,storage,action_name,planner) super (nil,action_name)
|
|||
|
self.st = storage
|
|||
|
self.evaluator_ready_to_kill = planner:evaluator(stalker_ids.property_ready_to_kill)
|
|||
|
self.rand_dif = math.random(-30,30)/100
|
|||
|
self.ddr = math.random() < 0.5 and 1 or -1
|
|||
|
end
|
|||
|
function action_monster_defend:initialize()
|
|||
|
action_base.initialize(self)
|
|||
|
local npc = self.object
|
|||
|
npc:set_desired_position()
|
|||
|
npc:set_desired_direction()
|
|||
|
npc:set_mental_state(anim.danger)
|
|||
|
npc:set_path_type(game_object.level_path)
|
|||
|
npc:set_dest_level_vertex_id(npc:level_vertex_id())
|
|||
|
end
|
|||
|
function action_monster_defend:execute()
|
|||
|
action_base.execute(self)
|
|||
|
local npc = self.object
|
|||
|
local target = self.st.target and (db.storage[self.st.target] and db.storage[self.st.target].object or level.object_by_id(self.st.target))
|
|||
|
if not target then
|
|||
|
return
|
|||
|
end
|
|||
|
if npc:path_type() ~= game_object.level_path then
|
|||
|
npc:set_path_type(game_object.level_path)
|
|||
|
end
|
|||
|
local wpn = npc:best_weapon()
|
|||
|
if not wpn then
|
|||
|
return
|
|||
|
end
|
|||
|
|
|||
|
if self.evaluator_ready_to_kill:evaluate() ~= true and wpn:get_ammo_in_magazine() ~= 0 then -- <09><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
|
|||
|
if self.weapon_fix_time then
|
|||
|
if self.weapon_fix_time < time_global() then
|
|||
|
self.st.target = nil
|
|||
|
self.st.check_time = time_global()+5000
|
|||
|
return
|
|||
|
end
|
|||
|
else
|
|||
|
self.weapon_fix_time = time_global()+4000
|
|||
|
end
|
|||
|
else
|
|||
|
self.weapon_fix_time = nil
|
|||
|
end
|
|||
|
|
|||
|
if npc:id()%2 == 0 and wpn:get_ammo_in_magazine() == 0 and not npc:path_completed() then
|
|||
|
npc:set_sight(look.path_dir,nil,0)
|
|||
|
npc:set_item(object.aim1,wpn)
|
|||
|
elseif not npc:see(target) then
|
|||
|
npc:set_sight(target,true,false)
|
|||
|
npc:set_item(object.aim1,wpn)
|
|||
|
else
|
|||
|
local fire_point = rx_utils.safe_bone_pos(target,"bip01_neck") -- target:center() rx_utils.safe_bone_pos(target,"bip01_neck") target:bone_position(rx_utils.get_fire_bone(target:section()))
|
|||
|
-- fire_point.y = fire_point.y+0.15
|
|||
|
npc:set_sight(look.direction,fire_point:sub(npc:bone_position("bip01_neck")))
|
|||
|
-- npc:set_sight(look.point,fire_point,true)
|
|||
|
local magsize = math.min(rx_utils.get_mag_size(wpn:section()),50)
|
|||
|
local min_queue = math.floor(magsize/5)
|
|||
|
local max_queue = math.ceil(magsize/3)
|
|||
|
npc:set_item(object.fire1,wpn,math.random(min_queue,max_queue),700)
|
|||
|
end
|
|||
|
|
|||
|
local dist = npc:position():distance_to_sqr(target:position())
|
|||
|
local target_be = target:get_enemy()
|
|||
|
if not (target_be and target_be:id() == npc:id()) then
|
|||
|
if dist < md_walk_dist then
|
|||
|
npc:set_movement_type(move.walk)
|
|||
|
local vertex = self:get_dodge_vertex(npc:level_vertex_id(),target:position(),0,1)
|
|||
|
if vertex then
|
|||
|
npc:set_dest_level_vertex_id(vertex)
|
|||
|
end
|
|||
|
end
|
|||
|
return
|
|||
|
end
|
|||
|
|
|||
|
if dist < md_run_dist then
|
|||
|
npc:set_movement_type(move.run)
|
|||
|
npc:set_body_state(move.standing)
|
|||
|
elseif dist < md_walk_dist then
|
|||
|
npc:set_movement_type(move.walk)
|
|||
|
else
|
|||
|
return
|
|||
|
end
|
|||
|
|
|||
|
local vertex = self:get_dodge_vertex(npc:level_vertex_id(),target:position(),md_monsters[target:clsid()])
|
|||
|
if not vertex then
|
|||
|
self.ddr = -self.ddr
|
|||
|
self.st.target = nil
|
|||
|
self.st.check_time = time_global()+4000
|
|||
|
return
|
|||
|
end
|
|||
|
npc:set_dest_level_vertex_id(vertex)
|
|||
|
end
|
|||
|
function action_monster_defend:finalize()
|
|||
|
action_base.finalize(self)
|
|||
|
self.weapon_fix_time = nil
|
|||
|
end
|
|||
|
|
|||
|
local _H_step = math.pi/6
|
|||
|
function action_monster_defend:get_dodge_vertex(lvid,pos,imod,tc)
|
|||
|
local npc = self.object
|
|||
|
local npc_pos = npc:position()
|
|||
|
local dir = vector():sub(npc:position(),pos)
|
|||
|
local dH,dP,res = dir:getH()+self.rand_dif,dir:getP()
|
|||
|
local found,mod
|
|||
|
imod = imod or 0
|
|||
|
for i=0,(tc or 5) do
|
|||
|
mod = imod > 0 and imod+i*_H_step or imod-i*_H_step
|
|||
|
if mod > 2.6 then
|
|||
|
break
|
|||
|
end
|
|||
|
res = npc:vertex_in_direction(lvid,vector():setHP(dH+mod*self.ddr,dP),4)
|
|||
|
if (lvid ~= res and npc:accessible(res) and level.vertex_position(res):distance_to_sqr(npc_pos) > 8) then
|
|||
|
found = true
|
|||
|
break
|
|||
|
end
|
|||
|
end
|
|||
|
return found and res
|
|||
|
end
|
|||
|
|
|||
|
class "action_take_cover" (action_base)
|
|||
|
function action_take_cover:__init (npc,storage,action_name,action) super (nil,action_name)
|
|||
|
self.st = storage
|
|||
|
self.inherited = action
|
|||
|
end
|
|||
|
function action_take_cover:initialize()
|
|||
|
self.inherited:initialize()
|
|||
|
local npc = self.object
|
|||
|
if math.random() > npc.health-0.15 then
|
|||
|
npc:set_movement_type(move.run)
|
|||
|
end
|
|||
|
local wpn = npc:best_weapon()
|
|||
|
self.max_queue = wpn and math.ceil(rx_utils.get_mag_size(wpn:section())/5) or 5
|
|||
|
rx_ai.subscribe_for_events(npc,self)
|
|||
|
end
|
|||
|
function action_take_cover:execute()
|
|||
|
self.inherited:execute()
|
|||
|
local npc = self.object
|
|||
|
|
|||
|
if self.use_crouch == true then
|
|||
|
npc:set_body_state(move.crouch)
|
|||
|
end
|
|||
|
|
|||
|
local enemy = npc:best_enemy()
|
|||
|
if enemy and npc:see(enemy) then
|
|||
|
local npc_pos,enemy_pos = npc:position(),enemy:position()
|
|||
|
if math.abs(npc_pos.y - enemy_pos.y) > 2 then
|
|||
|
local int = npc_pos:distance_to(enemy_pos)*26
|
|||
|
npc:set_item(object.fire1,npc:best_weapon(),math.random(1,self.max_queue),int < 400 and 400 or int > 2500 and 2500 or int)
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
function action_take_cover:hit_callback(amount)
|
|||
|
local npc = self.object
|
|||
|
npc:set_movement_type(move.run)
|
|||
|
if self.use_crouch == nil then
|
|||
|
self.use_crouch = math.random() < 0.35
|
|||
|
local wpn = npc:best_weapon()
|
|||
|
self.max_queue = wpn and math.ceil(rx_utils.get_mag_size(wpn:section())/3) or 10
|
|||
|
end
|
|||
|
end
|
|||
|
function action_take_cover:finalize()
|
|||
|
self.inherited:finalize()
|
|||
|
self.use_crouch = nil
|
|||
|
rx_ai.unsubscribe_from_events(self.object:id(),self)
|
|||
|
end
|
|||
|
|
|||
|
|
|||
|
class "evaluator_sudden_attack" (property_evaluator)
|
|||
|
function evaluator_sudden_attack:__init(npc,storage,name) super (nil,name)
|
|||
|
self.st = storage
|
|||
|
-- rx_ai.subscribe_for_events(npc,self)
|
|||
|
end
|
|||
|
function evaluator_sudden_attack:evaluate()
|
|||
|
local npc = self.object
|
|||
|
local be = npc:best_enemy()
|
|||
|
if not be then
|
|||
|
return true
|
|||
|
end
|
|||
|
if self.st.enable_panic then
|
|||
|
return false
|
|||
|
end
|
|||
|
local dist = npc:position():distance_to(be:position())
|
|||
|
if dist > 150 then
|
|||
|
self.storage:set_property(stalker_ids.property_use_suddenness,false)
|
|||
|
return true
|
|||
|
end
|
|||
|
return true
|
|||
|
end
|
|||
|
function evaluator_sudden_attack:hit_callback(amount,_,who)
|
|||
|
if who and amount > 2 then
|
|||
|
self.storage:set_property(stalker_ids.property_use_suddenness,false)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
|
|||
|
class "evaluator_low_cover" (property_evaluator)
|
|||
|
function evaluator_low_cover:__init(npc,storage,name) super (nil,name)
|
|||
|
self.st = storage
|
|||
|
end
|
|||
|
function evaluator_low_cover:evaluate()
|
|||
|
local npc = self.object
|
|||
|
local be = npc:best_enemy()
|
|||
|
if not be then
|
|||
|
return false
|
|||
|
end
|
|||
|
if not self.storage:property(stalker_ids.property_in_cover) then
|
|||
|
return false
|
|||
|
end
|
|||
|
if not npc:best_weapon() then
|
|||
|
return false
|
|||
|
end
|
|||
|
local npc_pos,enemy_pos = npc:position(),npc:memory_position(be)
|
|||
|
local cover = npc:best_cover(npc_pos, enemy_pos, 1, 5, 150)
|
|||
|
if not cover then
|
|||
|
return false
|
|||
|
end
|
|||
|
local cover_pos = cover:position()
|
|||
|
if npc_pos:distance_to(cover_pos) > 0.1 then
|
|||
|
return false
|
|||
|
end
|
|||
|
local lvid = cover:level_vertex_id()
|
|||
|
local dir = vector():sub(enemy_pos,cover_pos)
|
|||
|
|
|||
|
local low = level.low_cover_in_direction(lvid,dir)
|
|||
|
local high = level.high_cover_in_direction(lvid,dir)
|
|||
|
|
|||
|
return (low+0.2 < high)
|
|||
|
end
|
|||
|
|
|||
|
----------------------------------------------------------------------------------------------------------------------
|
|||
|
-- BINDER
|
|||
|
----------------------------------------------------------------------------------------------------------------------
|
|||
|
|
|||
|
evid_monster_defend = rx_ai.base_id+45
|
|||
|
evid_sudden_attack = evid_monster_defend+1
|
|||
|
actid_monster_defend = stalker_ids.action_get_distance
|
|||
|
|
|||
|
function add_combat(npc,st)
|
|||
|
local storage = rx_ai.get_storage(npc:id(),"combat_add")
|
|||
|
local manager = npc:motivation_action_manager()
|
|||
|
local combat_action = manager:action(stalker_ids.action_combat_planner)
|
|||
|
local combat_action_planner = cast_planner(combat_action)
|
|||
|
|
|||
|
-- MONSTER DEFEND
|
|||
|
if md_enabled and npc:character_rank() >= md_min_rank then
|
|||
|
combat_action_planner:add_evaluator(evid_monster_defend,evaluator_monster_defend(npc,storage,"eva_monster_defend"))
|
|||
|
local new_action = action_monster_defend(npc,storage,"monster_defend",combat_action_planner)
|
|||
|
new_action:add_precondition(world_property(stalker_ids.property_critically_wounded,false))
|
|||
|
new_action:add_precondition(world_property(stalker_ids.property_danger_grenade,false))
|
|||
|
new_action:add_precondition(world_property(stalker_ids.property_use_suddenness,false))
|
|||
|
-- new_action:add_precondition(world_property(stalker_ids.property_ready_to_kill,true))
|
|||
|
new_action:add_precondition(world_property(stalker_ids.property_inside_anomaly+3,false)) -- eWorldPropertyInSmartCover
|
|||
|
new_action:add_precondition(world_property(stalker_ids.property_panic,false))
|
|||
|
new_action:add_precondition(world_property(stalker_ids.property_pure_enemy+2,false)) -- eWorldPropertyEnemyWounded
|
|||
|
new_action:add_precondition(world_property(stalker_ids.property_pure_enemy+5,false)) -- eWorldPropertyPlayerOnThePath
|
|||
|
-- new_action:add_precondition(world_property(stalker_ids.property_critically_wounded+4,false)) -- eWorldPropertyTooFarToKillEnemy
|
|||
|
|
|||
|
-- new_action:add_precondition(world_property(stalker_ids.property_pure_enemy,true))
|
|||
|
new_action:add_precondition(world_property(evid_monster_defend,true))
|
|||
|
new_action:add_effect(world_property(stalker_ids.property_pure_enemy,false))
|
|||
|
new_action:add_effect(world_property(evid_monster_defend,false))
|
|||
|
|
|||
|
-- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
-- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
combat_action_planner:remove_action(stalker_ids.action_get_distance) -- <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
combat_action_planner:add_action(stalker_ids.action_get_distance,new_action)
|
|||
|
end
|
|||
|
-- TAKE COVER
|
|||
|
if run_on_hit then
|
|||
|
local old_action = combat_action_planner:action(stalker_ids.action_take_cover)
|
|||
|
old_action:remove_effect(stalker_ids.property_in_cover)
|
|||
|
old_action:remove_effect(stalker_ids.property_looked_out)
|
|||
|
old_action:remove_effect(stalker_ids.property_position_holded)
|
|||
|
old_action:remove_effect(stalker_ids.property_enemy_detoured)
|
|||
|
-- combat_action_planner:remove_action(stalker_ids.action_take_cover)
|
|||
|
|
|||
|
local new_action = action_take_cover(npc,storage,"monster_defend",old_action)
|
|||
|
new_action:add_precondition(world_property(stalker_ids.property_critically_wounded,false))
|
|||
|
new_action:add_precondition(world_property(stalker_ids.property_danger_grenade,false))
|
|||
|
new_action:add_precondition(world_property(stalker_ids.property_use_suddenness,false))
|
|||
|
new_action:add_precondition(world_property(stalker_ids.property_item_to_kill,true))
|
|||
|
new_action:add_precondition(world_property(stalker_ids.property_item_can_kill,true))
|
|||
|
new_action:add_precondition(world_property(stalker_ids.property_ready_to_kill,true))
|
|||
|
new_action:add_precondition(world_property(stalker_ids.property_in_cover,false))
|
|||
|
new_action:add_precondition(world_property(stalker_ids.property_inside_anomaly+3,false)) -- eWorldPropertyInSmartCover
|
|||
|
new_action:add_precondition(world_property(stalker_ids.property_pure_enemy+2,false)) -- eWorldPropertyEnemyWounded
|
|||
|
new_action:add_precondition(world_property(stalker_ids.property_pure_enemy+5,false)) -- eWorldPropertyPlayerOnThePath
|
|||
|
|
|||
|
new_action:add_effect(world_property(stalker_ids.property_in_cover,true))
|
|||
|
new_action:add_effect(world_property(stalker_ids.property_looked_out,false))
|
|||
|
new_action:add_effect(world_property(stalker_ids.property_position_holded,false))
|
|||
|
new_action:add_effect(world_property(stalker_ids.property_enemy_detoured,false))
|
|||
|
|
|||
|
combat_action_planner:add_action(stalker_ids.action_take_cover,new_action)
|
|||
|
end
|
|||
|
|
|||
|
-- SUDDEN ATTACK
|
|||
|
-- combat_action_planner:add_evaluator(evid_sudden_attack,evaluator_sudden_attack(npc,storage,"eva_sudden_attack"))
|
|||
|
-- local old_action = combat_action_planner:action(stalker_ids.action_sudden_attack)
|
|||
|
-- old_action:add_precondition(world_property(evid_sudden_attack,true))
|
|||
|
|
|||
|
-- LOW COVER
|
|||
|
-- combat_action_planner:remove_evaluator(stalker_ids.property_inside_anomaly+2) -- eWorldPropertyLowCover
|
|||
|
-- combat_action_planner:add_evaluator(stalker_ids.property_inside_anomaly+2,evaluator_low_cover(npc,storage,"eva_low_cover")) -- eWorldPropertyLowCover
|
|||
|
|
|||
|
-- if not set_inertia_time_15 then
|
|||
|
-- local danger_action_planner = cast_planner(manager:action(stalker_ids.action_danger_planner))
|
|||
|
|
|||
|
-- local danger_unknown_planner = cast_planner(danger_action_planner:action(stalker_ids.action_danger_unknown_planner))
|
|||
|
-- set_inertia_time_15 = danger_unknown_planner:action(stalker_ids.action_danger_unknown_look_around).initialize -- 15000
|
|||
|
|
|||
|
-- local danger_indirection_planner = cast_planner(danger_action_planner:action(stalker_ids.action_danger_in_direction_planner))
|
|||
|
-- set_inertia_time_5_10 = danger_indirection_planner:action(stalker_ids.action_danger_in_direction_hold_position).initialize -- 5000-10000
|
|||
|
-- end
|
|||
|
|
|||
|
-- local low_cover_action = combat_action_planner:action(stalker_ids.action_kill_if_enemy_critically_wounded+8)
|
|||
|
-- local low_cover_planner = cast_planner(low_cover_action)
|
|||
|
-- st.lowcover_hold_position_act = low_cover_planner:action(stalker_ids.action_hold_position)
|
|||
|
end
|
|||
|
|
|||
|
----------------------------------------------------------------------------------------------------------------------
|
|||
|
-- UPDATE
|
|||
|
----------------------------------------------------------------------------------------------------------------------
|
|||
|
|
|||
|
function combat_planner_update(npc,st)
|
|||
|
if not st.combat_planner then
|
|||
|
st.combat_planner = cast_planner(st.planner:action(stalker_ids.action_combat_planner))
|
|||
|
end
|
|||
|
local action_id = st.combat_planner:current_action_id()
|
|||
|
-- <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
if action_id == stalker_ids.action_sudden_attack and not npc:active_item() then
|
|||
|
npc:set_item(object.idle,npc:best_weapon()) --rx_utils.get_weapon(npc)
|
|||
|
end
|
|||
|
if action_id ~= st.combat_planner_action_id then
|
|||
|
st.combat_planner_action_id = action_id
|
|||
|
st.combat_planner_fix_timer = nil
|
|||
|
if action_id == stalker_ids.action_get_ready_to_kill or action_id == stalker_ids.action_get_ready_to_kill+1 then
|
|||
|
st.combat_planner_fix_timer = time_global()+3300
|
|||
|
-- elseif action_id == stalker_ids.action_look_out then
|
|||
|
-- st.combat_planner_fix_timer = time_global()+15000
|
|||
|
-- elseif action_id == stalker_ids.action_critically_wounded then
|
|||
|
-- st.combat_planner_fix_timer = time_global()+5000
|
|||
|
-- elseif action_id == stalker_ids.action_kill_if_enemy_critically_wounded+8 then -- eWorldOperatorLowCover
|
|||
|
-- set_inertia_time_5_10(st.lowcover_hold_position_act)
|
|||
|
elseif action_id == stalker_ids.action_search_enemy then
|
|||
|
if math.random() < 0.3 then
|
|||
|
npc:set_movement_type(move.run)
|
|||
|
end
|
|||
|
end
|
|||
|
elseif st.combat_planner_fix_timer and st.combat_planner_fix_timer < time_global() then
|
|||
|
st.combat_planner_fix_timer = nil
|
|||
|
if action_id == stalker_ids.action_get_ready_to_kill then
|
|||
|
-- <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> strap
|
|||
|
-- <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
local wpn = npc:active_item()
|
|||
|
if not npc:weapon_unstrapped() then
|
|||
|
npc:drop_item(wpn)
|
|||
|
elseif wpn and wpn:get_ammo_in_magazine() == wpn:get_ammo_total() then
|
|||
|
wpn:unload_magazine()
|
|||
|
end
|
|||
|
elseif action_id == stalker_ids.action_get_ready_to_kill+1 then -- eWorldOperatorGetReadyToDetour
|
|||
|
-- <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
local wpn = npc:active_item()
|
|||
|
local aminmag = wpn and wpn:get_ammo_in_magazine()
|
|||
|
if wpn and aminmag == wpn:get_ammo_total() then
|
|||
|
local magsize = rx_utils.get_mag_size(wpn:section())
|
|||
|
wpn:set_ammo_elapsed(aminmag < magsize and magsize or aminmag+10)
|
|||
|
end
|
|||
|
-- elseif action_id == stalker_ids.action_look_out then
|
|||
|
-- -- <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
-- local enemy = npc:best_enemy()
|
|||
|
-- local dist = npc:position():distance_to(npc:memory_position(enemy))
|
|||
|
-- npc:enable_memory_object(enemy,false)
|
|||
|
-- elseif action_id == stalker_ids.action_critically_wounded then
|
|||
|
end
|
|||
|
end
|
|||
|
end
|