648 lines
18 KiB
Plaintext
648 lines
18 KiB
Plaintext
|
---- Ai Additions ----
|
|||
|
---- Rulix aka Bak ---
|
|||
|
--evaspy = rx_utils.prof_spy()
|
|||
|
rx_utils.init()
|
|||
|
rx_ini = ini_file([[misc\ai_additions\misc.ltx]])
|
|||
|
|
|||
|
ids_to_remove = {}
|
|||
|
|
|||
|
local death_sound_prob = rx_utils.read_from_ini(rx_ini,"sound","death_probability",50)/100
|
|||
|
local ff_sound_prob = rx_utils.read_from_ini(rx_ini,"sound","friendlyfire_probability",50)/100
|
|||
|
local grenade_sound_prob = rx_utils.read_from_ini(rx_ini,"sound","grenade_probability",50)/100
|
|||
|
|
|||
|
function printf(str,...)
|
|||
|
rx_utils.printf(str,...)
|
|||
|
end
|
|||
|
|
|||
|
-----------------------------------storage-------------------------------------
|
|||
|
function get_storage(id,name)
|
|||
|
local st = db.storage[id]
|
|||
|
if not st then
|
|||
|
local obj = level.object_by_id(id)
|
|||
|
local objname = obj and obj:character_name() or "<nil>"
|
|||
|
printf("get_storage[%s|%s]:not npc storage!!! (%s)",id,name,objname)
|
|||
|
return {}
|
|||
|
end
|
|||
|
if not st.rx_ai then
|
|||
|
st.rx_ai = {}
|
|||
|
end
|
|||
|
if not name then
|
|||
|
return st.rx_ai
|
|||
|
end
|
|||
|
if not st.rx_ai[name] then
|
|||
|
st.rx_ai[name] = {}
|
|||
|
end
|
|||
|
return st.rx_ai[name]
|
|||
|
end
|
|||
|
|
|||
|
function get_var(npc,name,def)
|
|||
|
local st = npc and db.storage[npc:id()]
|
|||
|
if st.pstor and st.pstor[name] then
|
|||
|
return st.pstor[name]
|
|||
|
end
|
|||
|
return def
|
|||
|
end
|
|||
|
|
|||
|
function save_var(npc,name,val)
|
|||
|
local st = db.storage[npc:id()]
|
|||
|
if not st.pstor then
|
|||
|
st.pstor = {}
|
|||
|
end
|
|||
|
st.pstor[name] = val
|
|||
|
return val
|
|||
|
end
|
|||
|
|
|||
|
------------------------------------callbacks----------------------------------
|
|||
|
|
|||
|
function actor_update()
|
|||
|
if #ids_to_remove > 0 then
|
|||
|
for i=1,#ids_to_remove do
|
|||
|
local sobj = alife():object(ids_to_remove[i])
|
|||
|
if sobj then
|
|||
|
alife():release(sobj,true)
|
|||
|
end
|
|||
|
end
|
|||
|
ids_to_remove = {}
|
|||
|
end
|
|||
|
if rx_wmgr then
|
|||
|
rx_wmgr.global_update()
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function actor_net_spawn()
|
|||
|
if rx_gl then
|
|||
|
rx_gl.net_spawn()
|
|||
|
end
|
|||
|
if rx_wmgr then
|
|||
|
rx_wmgr.init()
|
|||
|
end
|
|||
|
if xr_corpse_detection then
|
|||
|
xr_corpse_detection.actor_net_spawn()
|
|||
|
end
|
|||
|
rx_sound.load_sounds()
|
|||
|
end
|
|||
|
|
|||
|
function actor_item_take(item)
|
|||
|
if xr_corpse_detection then
|
|||
|
xr_corpse_detection.actor_item_take(item)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function actor_save()
|
|||
|
if rx_wmgr then
|
|||
|
rx_wmgr.return_all()
|
|||
|
end
|
|||
|
if rx_addons then
|
|||
|
rx_addons.actor_save()
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function npc_update(npc,st) -- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
st = st.rx_ai --get_storage(npc:id())
|
|||
|
if not st then
|
|||
|
printf("npc_update[%s]:not st!!!",npc:name())
|
|||
|
return
|
|||
|
end
|
|||
|
if rx_wmgr then
|
|||
|
rx_wmgr.npc_update(npc,st)
|
|||
|
end
|
|||
|
if rx_addons then
|
|||
|
rx_addons.npc_update(npc,st)
|
|||
|
end
|
|||
|
eat_medkit(npc)
|
|||
|
look_into_optical_sight(npc)
|
|||
|
-- planner
|
|||
|
local action_id = st.planner:current_action_id()
|
|||
|
if action_id ~= st.planner_action_id then
|
|||
|
issue_event(npc,"action_switch",action_id,st.planner_action_id)
|
|||
|
if st.planner_action_id == stalker_ids.action_combat_planner then
|
|||
|
st.combat_planner_fix_timer = nil
|
|||
|
end
|
|||
|
st.planner_action_id = action_id
|
|||
|
end
|
|||
|
if action_id == stalker_ids.action_combat_planner and rx_combat then
|
|||
|
rx_combat.combat_planner_update(npc,st)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function squad_switch_online(squad)
|
|||
|
end
|
|||
|
|
|||
|
function squad_switch_offline(squad)
|
|||
|
end
|
|||
|
|
|||
|
function npc_net_spawn(npc)
|
|||
|
local st = get_storage(npc:id())
|
|||
|
st.planner = npc:motivation_action_manager()
|
|||
|
if rx_kill_wounded then
|
|||
|
rx_kill_wounded.add_kill_wounded(npc)
|
|||
|
end
|
|||
|
if rx_combat then
|
|||
|
rx_combat.add_combat(npc,st)
|
|||
|
end
|
|||
|
common_planner_pair(npc)
|
|||
|
rx_sound.init_npc_sound(npc)
|
|||
|
end
|
|||
|
|
|||
|
function corpse_net_spawn(npc,loaded)
|
|||
|
if xr_corpse_detection and loaded then
|
|||
|
xr_corpse_detection.corpse_net_spawn(npc)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function npc_switch_online(id)
|
|||
|
end
|
|||
|
|
|||
|
function npc_switch_offline(id) -- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
if rx_addons then
|
|||
|
rx_addons.npc_switch_offline(id)
|
|||
|
end
|
|||
|
if rx_wmgr then
|
|||
|
rx_wmgr.kill_wm(id,nil,true)
|
|||
|
end
|
|||
|
unsubscribe_from_events(id)
|
|||
|
end
|
|||
|
|
|||
|
function npc_net_destroy(npc)
|
|||
|
if not npc:alive() then
|
|||
|
return
|
|||
|
end
|
|||
|
if rx_wmgr then
|
|||
|
rx_wmgr.clear_wm(npc)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
local hit_bone_id = -1
|
|||
|
function npc_death(npc,who)
|
|||
|
if npc then
|
|||
|
local npc_id = npc:id()
|
|||
|
if rx_wmgr then
|
|||
|
rx_wmgr.kill_wm(npc_id,true)
|
|||
|
end
|
|||
|
if xr_corpse_detection then
|
|||
|
xr_corpse_detection.npc_death(npc,who)
|
|||
|
end
|
|||
|
issue_event(npc,"death_callback",who)
|
|||
|
unsubscribe_from_events(npc_id)
|
|||
|
-- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
if (hit_bone_id >= 15 and hit_bone_id <= 19) or math.random() > death_sound_prob then
|
|||
|
npc:set_sound_mask(-1)
|
|||
|
end
|
|||
|
-- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
local st = db.storage[npc_id]
|
|||
|
if not (st and st.rx_ai and st.pstor) then
|
|||
|
return
|
|||
|
end
|
|||
|
local pstor = st.pstor
|
|||
|
for i,val in ipairs({'fa_target','gl_charged','kw_type','courage','kn_spawn','wounded_fight','wounded_state','wounded_sound','wounded_victim','wounded_time'}) do
|
|||
|
pstor[val] = nil
|
|||
|
end
|
|||
|
-- fixing possible afterlife evaluators activity
|
|||
|
local planner = st.rx_ai.planner or npc:motivation_action_manager()
|
|||
|
for id,ret in pairs(death_disable_evas) do
|
|||
|
planner:remove_evaluator(id)
|
|||
|
planner:add_evaluator(id,property_evaluator_const(ret))
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function npc_hit(npc,amount,dir,who,bone_id)
|
|||
|
if npc and amount > 0 then
|
|||
|
hit_bone_id = bone_id
|
|||
|
issue_event(npc,"hit_callback",amount,dir,who,bone_id)
|
|||
|
get_storage(npc:id()).hit_by_anomaly = rx_utils.is_anomaly(who) or nil
|
|||
|
-- sound part
|
|||
|
local snd
|
|||
|
if math.random() < ff_sound_prob and who and who:alive() and not xr_wounded.is_wounded(npc) and who:id() ~= npc:id() then
|
|||
|
if npc:relation(who) ~= game_object.enemy and who:relation(npc) ~= game_object.enemy then
|
|||
|
if npc:position():distance_to_sqr(who:position()) < 1000 then
|
|||
|
if bone_id == 0 then
|
|||
|
snd = "friendly_grenade"
|
|||
|
else
|
|||
|
snd = "friendly_fire"
|
|||
|
end
|
|||
|
end
|
|||
|
else
|
|||
|
local actid = npc:motivation_action_manager():current_action_id()
|
|||
|
if actid >= base_id and actid < base_id+100 then
|
|||
|
snd = "npc_hit"
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
if snd then
|
|||
|
rx_sound.set_sound_play(npc:id(),snd)
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function npc_hear(npc,who_id,sound_type,sound_position,sound_power)
|
|||
|
-- issue_event(npc,"hear_callback",who_id,sound_type,sound_position,sound_power)
|
|||
|
end
|
|||
|
|
|||
|
function npc_item_take(npc,item)
|
|||
|
if npc then
|
|||
|
if rx_addons then
|
|||
|
rx_addons.npc_item_take(npc,item)
|
|||
|
end
|
|||
|
issue_event(npc,"on_item_take",item)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function npc_item_drop(npc,item)
|
|||
|
if npc then
|
|||
|
issue_event(npc,"on_item_drop",item)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function monster_death(npc,who)
|
|||
|
if xr_corpse_detection then
|
|||
|
xr_corpse_detection.npc_death(npc,who)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
------------------------------------events-------------------------------------
|
|||
|
function issue_event(npc,name,...)
|
|||
|
local st = get_storage(npc:id(),"events")
|
|||
|
for k,v in pairs(st) do
|
|||
|
if v and k[name] then
|
|||
|
k[name](k,...)
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function broadcast_event(name,...)
|
|||
|
for id,st in pairs(db.storage) do
|
|||
|
if st.rx_ai then
|
|||
|
st = st.rx_ai.events
|
|||
|
if st then
|
|||
|
for k,v in pairs(st) do
|
|||
|
if v and k[name] then
|
|||
|
k[name](k,...)
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function subscribe_for_events(npc,obj)
|
|||
|
get_storage(npc:id(),"events")[obj] = true
|
|||
|
end
|
|||
|
|
|||
|
function unsubscribe_from_events(npc_id,obj)
|
|||
|
if obj then
|
|||
|
get_storage(npc_id,"events")[obj] = nil
|
|||
|
else
|
|||
|
get_storage(npc_id)["events"] = nil
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
------------------------------------planner------------------------------------
|
|||
|
base_id = 18800
|
|||
|
reset_protected_actions = {}
|
|||
|
no_talk_actions = {}
|
|||
|
death_disable_evas = {
|
|||
|
--[xr_evaluators_id.state_mgr + 1] = true,
|
|||
|
--[xr_evaluators_id.state_mgr + 2] = true,
|
|||
|
}
|
|||
|
|
|||
|
function is_active_action(npc,actid)
|
|||
|
if not actid then
|
|||
|
local mgr = npc:motivation_action_manager()
|
|||
|
actid = mgr and mgr:initialized() and mgr:current_action_id() or 0
|
|||
|
end
|
|||
|
return actid > base_id and actid < base_id+100
|
|||
|
end
|
|||
|
|
|||
|
function cant_talk(npc,actid)
|
|||
|
if not actid then
|
|||
|
local mgr = npc:motivation_action_manager()
|
|||
|
actid = mgr:initialized() and mgr:current_action_id() or 0
|
|||
|
end
|
|||
|
return no_talk_actions[actid] == true
|
|||
|
end
|
|||
|
|
|||
|
-- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
|||
|
-- <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>:
|
|||
|
-- rx_ai.reset_protected_actions[action_id] = true
|
|||
|
-- <20><><EFBFBD><EFBFBD><EFBFBD> rx_ai.process_postponed_setup(npc:id()) <20><> action:finalize()
|
|||
|
function process_postponed_setup(id)
|
|||
|
local stor = db.storage[id]
|
|||
|
if stor and stor.active_scheme then
|
|||
|
local mm = stor.move_mgr
|
|||
|
if mm.path_walk and mm.setup_movement_postponed then
|
|||
|
mm.setup_movement_postponed = nil
|
|||
|
mm:setup_movement_by_patrol_path()
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function is_reset_protected_action(npc,actid)
|
|||
|
if not actid then
|
|||
|
local mgr = npc:motivation_action_manager()
|
|||
|
actid = mgr:initialized() and mgr:current_action_id() or 0
|
|||
|
end
|
|||
|
return reset_protected_actions[actid] == true
|
|||
|
end
|
|||
|
|
|||
|
function load_schemes()
|
|||
|
if rx_reload then
|
|||
|
load_scheme("rx_reload","reload",modules.stype_stalker)
|
|||
|
end
|
|||
|
if rx_gl then
|
|||
|
load_scheme("rx_gl","launch_grenade",modules.stype_stalker)
|
|||
|
end
|
|||
|
if rx_facer then
|
|||
|
load_scheme("rx_facer","facer",modules.stype_stalker)
|
|||
|
end
|
|||
|
if rx_bandage then
|
|||
|
load_scheme("rx_bandage","bandage",modules.stype_stalker)
|
|||
|
end
|
|||
|
if rx_ff then
|
|||
|
load_scheme("rx_ff","rx_ff",modules.stype_stalker)
|
|||
|
end
|
|||
|
if rx_knife then
|
|||
|
load_scheme("rx_knife","rx_knife",modules.stype_stalker)
|
|||
|
end
|
|||
|
if xr_help_wounded then
|
|||
|
load_scheme("xr_help_wounded","help_wounded",modules.stype_stalker)
|
|||
|
end
|
|||
|
if xr_corpse_detection then
|
|||
|
load_scheme("xr_corpse_detection","corpse_detection",modules.stype_stalker)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function disable_schemes(npc)
|
|||
|
--[[if rx_reload then
|
|||
|
rx_reload.disable_scheme(npc,"reload")
|
|||
|
end
|
|||
|
if rx_gl then
|
|||
|
rx_gl.disable_scheme(npc,"launch_grenade")
|
|||
|
end
|
|||
|
if rx_facer then
|
|||
|
rx_facer.disable_scheme(npc,"facer")
|
|||
|
end
|
|||
|
if rx_knife then
|
|||
|
rx_knife.disable_scheme(npc,"knife")
|
|||
|
end]]
|
|||
|
end
|
|||
|
|
|||
|
function enable_schemes(ini,npc,section_logic)
|
|||
|
if rx_reload then
|
|||
|
rx_reload.set_scheme(npc,ini,"reload","reload")
|
|||
|
end
|
|||
|
if rx_gl then
|
|||
|
rx_gl.set_scheme(npc,ini,"launch_grenade","launch_grenade")
|
|||
|
end
|
|||
|
if rx_facer then
|
|||
|
rx_facer.set_scheme(npc,ini,"facer","facer")
|
|||
|
end
|
|||
|
if rx_bandage then
|
|||
|
rx_bandage.set_scheme(npc,ini,"bandage","bandage")
|
|||
|
end
|
|||
|
if rx_ff then
|
|||
|
rx_ff.set_scheme(npc,ini,"rx_ff","rx_ff")
|
|||
|
end
|
|||
|
if rx_knife then
|
|||
|
rx_knife.set_scheme(npc,ini,"rx_knife",section_logic)
|
|||
|
end
|
|||
|
if xr_help_wounded then
|
|||
|
xr_help_wounded.set_help_wounded(npc,ini,"help_wounded","help_wounded")
|
|||
|
end
|
|||
|
if xr_corpse_detection then
|
|||
|
xr_corpse_detection.set_corpse_detection(npc,ini,"corpse_detection","corpse_detection")
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function reset_schemes(npc, scheme, st, section)
|
|||
|
if xr_help_wounded then
|
|||
|
xr_help_wounded.reset_help_wounded(npc, scheme, st, section)
|
|||
|
end
|
|||
|
if xr_corpse_detection then
|
|||
|
xr_corpse_detection.reset_corpse_detection(npc, scheme, st, section)
|
|||
|
end
|
|||
|
if rx_bandage then
|
|||
|
rx_bandage.reset_scheme(npc, scheme, st, section)
|
|||
|
end
|
|||
|
if rx_knife then
|
|||
|
rx_knife.reset_scheme(npc, scheme, st, section)
|
|||
|
end
|
|||
|
if rx_wmgr then
|
|||
|
rx_wmgr.reset_scheme(npc, scheme, st, section)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function addCommonPrecondition(action)
|
|||
|
if rx_reload then
|
|||
|
action:add_precondition(world_property(rx_reload.evid_reload,false))
|
|||
|
end
|
|||
|
if rx_gl then
|
|||
|
action:add_precondition(world_property(rx_gl.evid_gl_fire,false))
|
|||
|
action:add_precondition(world_property(rx_gl.evid_gl_reload,false))
|
|||
|
end
|
|||
|
if rx_facer then
|
|||
|
action:add_precondition(world_property(rx_facer.evid_facer,false))
|
|||
|
end
|
|||
|
if rx_bandage then
|
|||
|
action:add_precondition(world_property(rx_bandage.evid_bandage,false))
|
|||
|
end
|
|||
|
if rx_knife then
|
|||
|
action:add_precondition(world_property(rx_knife.evid_knife_attack,false))
|
|||
|
end
|
|||
|
if xr_help_wounded then
|
|||
|
action:add_precondition(world_property(xr_help_wounded.evid_wounded_exist,false))
|
|||
|
end
|
|||
|
if xr_corpse_detection then
|
|||
|
action:add_precondition(world_property(xr_corpse_detection.evid_corpse_exist,false))
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
------------------------------------eating----------------------------------------
|
|||
|
local eating = {enabled = rx_ini:section_exist("npc_eating") and rx_ini:r_bool("npc_eating","enabled")}
|
|||
|
function eat_init()
|
|||
|
local sect = "npc_eating"
|
|||
|
eating.exc_comms = rx_utils.parse_list(rx_ini,sect,"excluded_communities",true)
|
|||
|
eating.exc_npcs = rx_utils.parse_list(rx_ini,sect,"excluded_npcs",true)
|
|||
|
eating.ic = rx_utils.read_from_ini(rx_ini,sect,"in_combat",false,0)
|
|||
|
eating.oc = rx_utils.read_from_ini(rx_ini,sect,"out_combat",true,0)
|
|||
|
eating.max_h = rx_utils.read_from_ini(rx_ini,sect,"medkit_health",50)/100
|
|||
|
eating.min_b = rx_utils.read_from_ini(rx_ini,sect,"bandage_bleeding",0.2)
|
|||
|
eating.medkits = rx_utils.parse_list(rx_ini,sect,"medkits")
|
|||
|
eating.bandages = rx_utils.parse_list(rx_ini,sect,"bandages")
|
|||
|
eating.delay = rx_utils.parse_list(rx_ini,sect,"delay")
|
|||
|
end
|
|||
|
function eat_medkit(npc)
|
|||
|
if not eating.enabled then
|
|||
|
return
|
|||
|
end
|
|||
|
if not eating.max_h then
|
|||
|
eat_init()
|
|||
|
end
|
|||
|
local st = get_storage(npc:id(),"eating")
|
|||
|
if st.disabled then
|
|||
|
return
|
|||
|
elseif st.disabled == nil then
|
|||
|
st.disabled = false
|
|||
|
if eating.exc_comms[npc:character_community()] or eating.exc_npcs[npc:name()] then
|
|||
|
st.disabled = true
|
|||
|
-- printf("[%s]eating disabled",npc:character_name())
|
|||
|
end
|
|||
|
return
|
|||
|
end
|
|||
|
local enemy = npc:best_enemy()
|
|||
|
if xr_wounded.is_wounded(npc) or (not eating.ic and enemy) or (not eating.oc and not enemy) then
|
|||
|
st.item = nil
|
|||
|
st.time = nil
|
|||
|
return
|
|||
|
end
|
|||
|
if st.item and st.time then
|
|||
|
if st.time < time_global() then
|
|||
|
-- printf("[%s]eat[%s] enemy %s",npc:character_name(),st.item,tostring(enemy ~= nil))
|
|||
|
local med = npc:object(st.item)
|
|||
|
if med then
|
|||
|
rx_utils.eat_medkit(npc,med)
|
|||
|
end
|
|||
|
st.item = nil
|
|||
|
end
|
|||
|
return
|
|||
|
end
|
|||
|
if npc.health < eating.max_h and not xr_wounded.is_wounded(npc) then
|
|||
|
for k,v in ipairs(eating.medkits) do
|
|||
|
local medkit = npc:object(v)
|
|||
|
if medkit then
|
|||
|
-- printf("health[%s]=%s:set[%s]",npc:character_name(),npc.health,v)
|
|||
|
st.time = time_global()+math.random(eating.delay[1],eating.delay[2])
|
|||
|
st.item = v
|
|||
|
return
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
if npc:get_bleeding() > eating.min_b then
|
|||
|
for k,v in ipairs(eating.bandages) do
|
|||
|
local bandage = npc:object(v)
|
|||
|
if bandage then
|
|||
|
-- printf("bleeding[%s]=%s:set[%s]",npc:character_name(),npc:get_bleeding(),v)
|
|||
|
st.time = time_global()+math.random(eating.delay[1],eating.delay[2])
|
|||
|
st.item = v
|
|||
|
return
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
------------------------------------lios-----------------------------------------
|
|||
|
local lios = {enabled = rx_ini:section_exist("look_into_os") and rx_ini:r_bool("look_into_os","enabled")}
|
|||
|
function lios_init()
|
|||
|
local sect = "look_into_os"
|
|||
|
lios.exc_comms = rx_utils.parse_list(rx_ini,sect,"excluded_communities",true)
|
|||
|
lios.exc_npcs = rx_utils.parse_list(rx_ini,sect,"excluded_npcs",true)
|
|||
|
lios.range_add = rx_utils.read_from_ini(rx_ini,sect,"range_add",0.5)/100
|
|||
|
lios.fov_add = rx_utils.read_from_ini(rx_ini,sect,"fov_add",-0.3)/100
|
|||
|
lios.zoom_factor = {}
|
|||
|
lios.fire_dist = {}
|
|||
|
end
|
|||
|
function look_into_optical_sight(npc)
|
|||
|
if not lios.enabled then
|
|||
|
return
|
|||
|
elseif not lios.range_add then
|
|||
|
lios_init()
|
|||
|
end
|
|||
|
local storage = get_storage(npc:id(),"lios")
|
|||
|
if storage.disabled then
|
|||
|
return
|
|||
|
end
|
|||
|
if not storage.range then
|
|||
|
if lios.exc_comms[npc:character_community()] or lios.exc_npcs[npc:name()] then
|
|||
|
storage.disabled = true
|
|||
|
-- printf("[%s]lios disabled",npc:character_name())
|
|||
|
else
|
|||
|
storage.range = npc:range()
|
|||
|
storage.fov = npc:fov()
|
|||
|
storage.ch = false
|
|||
|
end
|
|||
|
return
|
|||
|
end
|
|||
|
local act = false
|
|||
|
local weapon = npc:active_item()
|
|||
|
if rx_utils.item_is_fa(weapon) and rx_utils.addon_attached(weapon,"sc") then
|
|||
|
-- printf("[%s]have os",npc:character_name())
|
|||
|
local move_type,mental_state = npc:movement_type(),npc:mental_state()
|
|||
|
if (move_type == move.stand or move_type == move.walk) and mental_state == anim.danger then
|
|||
|
-- printf("[%s]set lios",npc:character_name())
|
|||
|
act = true
|
|||
|
end
|
|||
|
end
|
|||
|
if storage.ch ~= act then
|
|||
|
local range,fov = storage.range,storage.fov
|
|||
|
if act == true then
|
|||
|
local function get_zoom_factor(sect)
|
|||
|
if lios.zoom_factor[sect] == nil then
|
|||
|
local scope = rx_utils.read_from_ini(nil,sect,"scope_status",nil) == 2 and rx_utils.read_from_ini(nil,sect,"scopes_sect",nil,1)
|
|||
|
if not scope then
|
|||
|
scope = sect
|
|||
|
end
|
|||
|
lios.zoom_factor[sect] = rx_utils.read_from_ini(nil,scope,"scope_zoom_factor",30)
|
|||
|
lios.fire_dist[sect] = rx_utils.read_from_ini(nil,sect,"fire_distance",150)
|
|||
|
-- printf("lios:%s zf = %s, fd = %s",sect,lios.zoom_factor[sect],lios.fire_dist[sect])
|
|||
|
end
|
|||
|
return lios.zoom_factor[sect],lios.fire_dist[sect]
|
|||
|
end
|
|||
|
local factor,max_range = get_zoom_factor(weapon:section())
|
|||
|
if factor < 80 and max_range > storage.range then
|
|||
|
factor = 30/factor
|
|||
|
range = range+range*lios.range_add*factor
|
|||
|
if range > max_range then
|
|||
|
range = max_range
|
|||
|
end
|
|||
|
fov = fov+fov*lios.fov_add*factor
|
|||
|
if fov < 40 then
|
|||
|
fov = 40
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
npc:set_range(range)
|
|||
|
npc:set_fov(fov)
|
|||
|
storage.ch = act
|
|||
|
-- printf("[%s]change to %s,set[%s][%s]",npc:character_name(),tostring(storage.ch),range,fov)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
-- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD> <20><><EFBFBD>
|
|||
|
class "evaluator_danger_grenade" (property_evaluator)
|
|||
|
function evaluator_danger_grenade:__init(npc,name) super (nil,name)
|
|||
|
-- rx_ai.subscribe_for_events(npc,self)
|
|||
|
end
|
|||
|
function evaluator_danger_grenade:evaluate()
|
|||
|
if not self.ceva then
|
|||
|
self.ceva = cast_planner(self.object:motivation_action_manager():action(stalker_ids.action_combat_planner)):evaluator(stalker_ids.property_danger_grenade)
|
|||
|
self.storage:set_property(stalker_ids.property_danger_grenade,false)
|
|||
|
return false
|
|||
|
end
|
|||
|
if self.ceva:evaluate() then
|
|||
|
local best_danger = self.object:best_danger()
|
|||
|
local grenade = best_danger:dependent_object()
|
|||
|
if grenade then
|
|||
|
if grenade:clsid() ~= clsid.obj_explosive and grenade:id() ~= self.react_id then -- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
self.react_id = grenade:id()
|
|||
|
local initiator = best_danger:object()
|
|||
|
if not (initiator and self.object:team() == initiator:team()) and math.random() < grenade_sound_prob then
|
|||
|
self.object:play_sound(stalker_ids.sound_grenade_alarm,2.5,1.0)
|
|||
|
end
|
|||
|
end
|
|||
|
self.storage:set_property(stalker_ids.property_danger_grenade,true)
|
|||
|
return true
|
|||
|
else -- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
self.react_id = nil
|
|||
|
end
|
|||
|
end
|
|||
|
self.storage:set_property(stalker_ids.property_danger_grenade,false)
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
function common_planner_pair(npc)
|
|||
|
local manager = npc:motivation_action_manager()
|
|||
|
manager:add_evaluator(stalker_ids.property_danger_grenade,evaluator_danger_grenade(npc,"eva_danger_grenade"))
|
|||
|
local action = manager:action(stalker_ids.action_danger_planner)
|
|||
|
action:add_effect(world_property(stalker_ids.property_danger_grenade,false))
|
|||
|
end
|