e4s-game/gamedata/scripts/xr_combat_ignore.script
2026-06-18 01:18:29 +03:00

198 lines
7.1 KiB
Text
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

--[[------------------------------------------------------------------------------------------------------------------
Игнорирование врагов
Чугай Александр
--------------------------------------------------------------------------------------------------------------------]]
local ignored_smart = {
zat_stalker_base_smart = true,
jup_b41 = true,
jup_a6 = true,
pri_a16 = true
}
fighting_with_actor_npcs = {
}
local smarts_by_no_assault_zones = {
["zat_a2_sr_no_assault"] = "zat_stalker_base_smart",
["jup_a6_sr_no_assault"] = "jup_a6",
["jup_b41_sr_no_assault"] = "jup_b41"
}
function is_enemy(obj, enemy, st, not_check_sim)
if not obj:alive() then
return false
end
if obj:critically_wounded() then
return true
end
if st.enabled == false then
return true
end
local overrides = st.overrides
local obj_id = obj:id()
local storage = db.storage[obj_id]
if storage == nil then
return true
end
storage.enemy_id = enemy:id()
--' Отсеиваем по зоне
local active_sector = storage.active_sector
if active_sector ~= nil then
if sr_danger.check_danger_position(enemy:position(), active_sector) == false then
-- obj:enable_memory_object( enemy, false )
return false
end
end
-- Проверка на зоны комбат игнора возле баз:
-- игнорировать если:
-- враг не актер.
-- сталкер находится в зоне.
-- смарт в котором находится сталкер не в состоянии тревоги.
if db.actor and enemy and enemy:id() ~= db.actor:id() then
for k,v in pairs (smarts_by_no_assault_zones) do
local zone = db.zone_by_name[k]
if zone and (utils.npc_in_zone(obj, zone) or utils.npc_in_zone(enemy, zone)) then
local smart = sim_board.get_sim_board():get_smart_by_name(v)
if smart and smart.base_on_actor_control ~= nil and smart.base_on_actor_control.status ~= smart_terrain_control.ALARM then
return false
end
end
end
end
local se_enemy = alife():object(enemy:id())
if se_enemy ~= nil and se_enemy.m_smart_terrain_id ~= nil and se_enemy.m_smart_terrain_id ~= 65535 then
local enemy_smart = alife():object(se_enemy.m_smart_terrain_id)
local smart_name = enemy_smart:name()
if ignored_smart[smart_name] == true then
-- obj:enable_memory_object( enemy, false )
return false
end
end
--printf("checking combat_ignore for stalker[%s] enemy name [%s] in section[%s]",obj:name(), enemy:name(),storage.active_section)
--' Если есть оверрайды, то работаем по ним.
if overrides and
overrides.combat_ignore
then
local ret_value = xr_logic.pick_section_from_condlist( enemy, obj, overrides.combat_ignore.condlist )
if ret_value == "true" then
--printf("pl:Disabling_memory_object[1] for stalker[%s] enemy name [%s] in section[%s]",obj:name(), enemy:name(),storage.active_section)
-- obj:enable_memory_object( enemy, false )
return false
end
return true
end
return true
end
----------------------------------------------------------------------------------------------------------------------
class "action_process_enemy"
function action_process_enemy:__init( obj, storage )
self.object = obj
self.st = storage
end
function action_process_enemy:enemy_callback( obj, enemy )
--' local obj_pos = self.object:position()
--' local ene_pos = enemy:position()
--' printf("FOUND ENEMY [%s](%s,%s,%s) -> [%s](%s,%s,%s)", self.object:name(), obj_pos.x, obj_pos.y, obj_pos.z,
--' enemy:name(), ene_pos.x, ene_pos.y, ene_pos.z)
if enemy:id() == db.actor:id() then
fighting_with_actor_npcs[obj:id()] = true
end
local is_obj_enemy = is_enemy( obj, enemy, self.st, false )
if is_obj_enemy == true then
local se_obj = alife():object(obj:id())
if se_obj and se_obj.m_smart_terrain_id ~= 65535 then
local smart_obj = alife():object(se_obj.m_smart_terrain_id)
smart_obj:set_alarm()
if db.actor and enemy and enemy:id() == db.actor:id() and smart_obj.base_on_actor_control ~= nil then
-- Fix start for detecting attacking of the base even when attacked npc is not near the base
local base_pos = db.zone_by_name[smart_obj.base_on_actor_control.noweap_zone]:position()
local distance = obj:position():distance_to(base_pos)
if distance < 100 then
smart_obj.base_on_actor_control:actor_attack()
end
-- Fix end for detecting attacking of the base even when attacked npc is not near the base
end
end
local se_enemy = alife():object(enemy:id())
if se_obj and se_enemy then
local sim_obj_registry = simulation_objects.get_sim_obj_registry()
if se_obj.group_id ~= 65535 and sim_obj_registry.objects[se_obj.group_id] ~= nil and
se_enemy.group_id ~= 65535 and sim_obj_registry.objects[se_enemy.group_id] == nil and
se_obj.position:distance_to_sqr(se_enemy.position) > 900 then
return false
end
end
end
return is_obj_enemy
end
function action_process_enemy:hit_callback(obj, amount, local_direction, who, bone_index)
if who == nil then
return
end
-- printf("_bp: action_process_enemy: hit_callback(): obj='%s'", obj:name())
if amount == 0 then
-- Кто-то стрельнул в воздух
return
end
if who:id() == db.actor:id() then
local overrides = self.st.overrides
if not overrides or not overrides.combat_ignore_keep_when_attacked then
--printf("_bp: action_process_enemy: hit_callback(): obj='%s': SCHEME DISABLED", obj:name())
self.st.enabled = false
end
end
end
----------------------------------------------------------------------------------------------------------------------
-- binder
----------------------------------------------------------------------------------------------------------------------
function add_to_binder( npc, ini, scheme, section, storage )
local new_action = this.action_process_enemy( npc, storage )
storage.action = new_action
end
function set_combat_ignore_checker( npc, ini, scheme)
local st = xr_logic.assign_storage_and_bind( npc, ini, scheme )
end
function reset_combat_ignore_checker(npc, scheme, st, section)
local storage = st.combat_ignore
npc:set_enemy_callback( storage.action.enemy_callback, storage.action )
-- Подписываемся на hit callback-и:
xr_logic.subscribe_action_for_events( npc, storage, storage.action )
storage.overrides = xr_logic.generic_scheme_overrides(npc)
storage.enabled = true
end
function disable_scheme( npc, scheme )
npc:set_enemy_callback()
-- Отписываемся от hit callback. Это делать обязательно, потому что иначе при переключении на другой набор
-- схем, в котором нет перехвата боя, продолжится вызываться callback в старом подписанном action-е.
local st = db.storage[npc:id()][scheme]
if st then
xr_logic.unsubscribe_action_from_events(npc, st, st.action)
end
end