------------------------------------------------------------------------------------ -- Схема: прячемся в кавере ------------------------------------------------------------------------------------ class "evaluator_need_cover" (property_evaluator) function evaluator_need_cover:__init(storage, name) super(nil, name) self.st = storage end function evaluator_need_cover:evaluate() return xr_logic.is_active(self.object, self.st) end ---------------------------------------------------------------------------------------------------------------------- class "action_cover" (action_base) function action_cover:__init (npc_name, action_name, storage) super(nil, action_name) self.st = storage end function action_cover:initialize() action_base.initialize(self) self.board = sim_board.get_sim_board() end function action_cover:activate_scheme() self.st.signals = {} self.board = sim_board.get_sim_board() --' Высчитываем кавер. local base_point = sim_board.get_sim_board():get_smart_by_name(self.st.smart).m_level_vertex_id local direction_vector = vector():set(math.random(-100,100), 0, math.random(-100,100)) local base_vertex_id = level.vertex_in_direction(base_point, direction_vector, math.random(self.st.radius_min,self.st.radius_max)) local self_random_position = level.vertex_position(base_vertex_id) --' Получаем врага, относительно которого надо искать кавер self.enemy_random_position = self_random_position --' дефолтовая позиция local cover = nil local tcover = nil local cover_dist = 2 while cover == nil and cover_dist <= 4 do cover = self.object:best_cover(self_random_position, self.enemy_random_position, cover_dist, 1, 150) cover_dist = cover_dist + 1 end if cover == nil then --printf("cover is [nil]") self.cover_vertex_id = base_vertex_id self.cover_position = self_random_position --printf("cover doesn't exists -- cover_vertex [%s] cover_position [%s]", tostring(self.cover_vertex_id), vec_to_str(self.cover_position)) else if tcover ~= nil then self.cover_vertex_id = tcover.cover_vertex_id self.cover_position = tcover.cover_position else self.cover_vertex_id = cover:level_vertex_id() self.cover_position = cover:position() end --printf("cover exists -- cover_vertex [%s] cover_position [%s]", tostring(self.cover_vertex_id), vec_to_str(self.cover_position)) end if not self.object:accessible(self.cover_position) then local ttp = vector():set(0,0,0) self.cover_vertex_id = self.object:accessible_nearest(self.cover_position, ttp) self.cover_position = level.vertex_position(self.cover_vertex_id) --printf("cover exists but not accesible -- cover_vertex [%s] cover_position [%s]", tostring(self.cover_vertex_id), vec_to_str(self.cover_position)) end local desired_direction = vector():sub(self.cover_position,self.enemy_random_position) printf("desired_direction = %s", vec_to_str(desired_direction)) if desired_direction ~= nil and not utils.vector_cmp(desired_direction, vector():set(0,0,0)) then desired_direction:normalize() self.object:set_desired_direction(desired_direction) end self.object:set_path_type(game_object.level_path) self.object:set_dest_level_vertex_id(self.cover_vertex_id) --printf("cover position is %s enemy position is %s", vec_to_str(self.cover_position), vec_to_str(self.enemy_random_position)) state_mgr.set_state(self.object, "assault") --printf("[%s]Setting cover %s", self.object:name(), self.cover_vertex_id) end function action_cover:execute() --printf("[%s] dist %s to %s", self.object:name(), self.cover_position:distance_to_sqr(self.object:position()), vec_to_str(self.cover_position)) --' Проверяем пришли ли в точку. if self.cover_position:distance_to_sqr(self.object:position()) <= 0.4 then local anim = xr_logic.pick_section_from_condlist(db.actor, self.object, self.st.anim) state_mgr.set_state(self.object, anim, nil, nil, {look_position = self.enemy_random_position}, nil, nil) else self.object:set_dest_level_vertex_id(self.cover_vertex_id) state_mgr.set_state(self.object, "assault") end if self.st.sound_idle ~= nil then xr_sound.set_sound_play(self.object:id(), self.st.sound_idle) end action_base.execute(self) end function action_cover:finalize() action_base.finalize(self) end --' Возвращает достиг ли персонаж точки начала работы схемы function action_cover:position_riched() return self.cover_position:distance_to_sqr(self.object:position()) <= 0.4 end ---------------------------------------------------------------------------------------------------------------------- -- binder ---------------------------------------------------------------------------------------------------------------------- function add_to_binder(npc, ini, scheme, section, storage) local operators = {} local properties = {} local manager = npc:motivation_action_manager() properties["event"] = xr_evaluators_id.reaction properties["need_cover"] = xr_evaluators_id.stohe_cover_base + 1 properties["state_mgr_logic_active"] = xr_evaluators_id.state_mgr + 4 operators["action_cover"] = xr_actions_id.stohe_cover_base + 1 -- evaluators manager:add_evaluator(properties["need_cover"], this.evaluator_need_cover(storage, "need_cover")) local new_action = this.action_cover(npc, "action_cover", storage) new_action:add_precondition(world_property(stalker_ids.property_alive,true)) new_action:add_precondition(world_property(stalker_ids.property_danger,false)) new_action:add_precondition(world_property(stalker_ids.property_enemy,false)) new_action:add_precondition(world_property(stalker_ids.property_anomaly,false)) new_action:add_precondition(world_property(xr_evaluators_id.sidor_wounded_base + 0,false)) new_action:add_precondition(world_property(properties["need_cover"],true)) new_action:add_effect(world_property(properties["need_cover"],false)) new_action:add_effect (world_property(properties["state_mgr_logic_active"], false)) manager:add_action(operators["action_cover"], new_action) -- Зарегистрировать все actions, в которых должен быть вызван метод reset_scheme при изменении настроек схемы: xr_logic.subscribe_action_for_events(npc, storage, new_action) new_action = manager:action(xr_actions_id.alife) new_action:add_precondition(world_property(properties["need_cover"], false)) end -- Включение схемы function set_scheme(npc, ini, scheme, section, gulag_name) local st = xr_logic.assign_storage_and_bind(npc, ini, scheme, section) st.logic = xr_logic.cfg_get_switch_conditions(ini, section, npc) st.smart = utils.cfg_get_string(ini, section, "smart", npc, false, "") st.anim = xr_logic.parse_condlist(npc, "anim", "anim", utils.cfg_get_string(ini, section, "anim", npc, false, "", "hide")) st.sound_idle= utils.cfg_get_string(ini, section, "sound_idle",npc, false, "") if st.smart == nil then abort("There is no path_walk and smart in xr_cover.") end st.use_attack_direction = utils.cfg_get_bool(ini, section, "use_attack_direction", npc, false, true) st.radius_min = utils.cfg_get_number(ini, section, "radius_min", npc, false, 3) st.radius_max = utils.cfg_get_number(ini, section, "radius_max", npc, false, 5) end