--[[---------------------------------------------------------------------------------------------------------- Боевая схема сталкеров группировки "Монолит" Чугай Александр ------------------------------------------------------------------------------------------------------------]] local base = xr_evaluators_id.combat_monolith_base local prop_enable = base + 0 local prop_see = base + 1 local prop_close = base + 2 local prop_on_pos = base + 3 base = xr_actions_id.combat_monolith_base local act_fight_close = base + 0 local act_fight_far = base + 1 local act_look_around = base + 2 local act_go_to_pos = base + 3 -------------------------------------------------------------------------------------------------------------- class "evaluator_combat_monolith" ( property_evaluator ) function evaluator_combat_monolith:__init( name, storage ) super ( nil, name ) self.st = storage end function evaluator_combat_monolith:evaluate() return db.storage[self.object:id()].script_combat_type == "monolith" end -------------------------------------------------------------------------------------------------------------- class "evaluator_see" ( property_evaluator ) function evaluator_see:__init( name, storage ) super ( nil, name ) self.st = storage end function evaluator_see:evaluate() local be = self.object:best_enemy() if self.object:alive() and be and self.object:see( be ) then self.st.last_seen_vert_id = be:level_vertex_id() return true else return false end end -------------------------------------------------------------------------------------------------------------- class "evaluator_close" ( property_evaluator ) function evaluator_close:__init( name, storage ) super ( nil, name ) self.st = storage self.close_dist_sqr = math.random( 20*20, 35*35 ) end function evaluator_close:evaluate() local be = self.object:best_enemy() return be ~= nil and self.object:position():distance_to_sqr( be:position() ) < self.close_dist_sqr end -------------------------------------------------------------------------------------------------------------- class "evaluator_on_pos" ( property_evaluator ) function evaluator_on_pos:__init( name, storage ) super ( nil, name ) self.st = storage end function evaluator_on_pos:evaluate() local r = self.object:level_vertex_id() == self.st.last_seen_vert_id --printf( tostring( r ) ) return r end -------------------------------------------------------------------------------------------------------------- class "action_fight_close" ( action_base ) function action_fight_close:__init( name, storage ) super ( nil, name ) self.st = storage end function action_fight_close:initialize() action_base.initialize( self ) state_mgr.set_state( self.object, "hide_fire", nil, nil, { look_object = self.object:best_enemy() } ) end function action_fight_close:execute() action_base.execute( self ) end function action_fight_close:finalize() action_base.finalize( self ) end -- Внимание: вызывается во всех actions function action_fight_close:hit_callback( obj, amount, local_direction, who, bone_index ) if who == nil then return end local be = self.object and self.object:best_enemy() -- если получили хит от текущего врага, то мы знаем, где он if be and who:id() == be:id() then self.st.last_seen_vert_id = be:level_vertex_id() end end -------------------------------------------------------------------------------------------------------------- class "action_fight_far" ( action_base ) function action_fight_far:__init( name, storage ) super ( nil, name ) self.st = storage end function action_fight_far:initialize() action_base.initialize( self ) -- self.object:set_node_evaluator () -- self.object:set_path_evaluator () self.object:set_desired_direction () self.object:set_desired_position () self.object:set_detail_path_type ( move.line ) self.object:set_path_type ( game_object.level_path ) state_mgr.set_state( self.object, "assault_fire", nil, nil, { look_object = self.object:best_enemy() } ) end function action_fight_far:execute() action_base.execute( self ) utils.send_to_nearest_accessible_vertex( self.object, self.object:best_enemy():level_vertex_id() ) end function action_fight_far:finalize() action_base.finalize( self ) end -------------------------------------------------------------------------------------------------------------- class "action_look_around" ( action_base ) function action_look_around:__init( name, storage ) super ( nil, name ) self.st = storage end function action_look_around:initialize() action_base.initialize( self ) self.forget_time = time_global() + 30000 self.change_dir_time = 0 end function action_look_around:execute() action_base.execute( self ) if self.forget_time < time_global() then printf("pl:Disabling_memory_object[9]") -- self.object:enable_memory_object( self.object:best_enemy(), false ) self.st.last_seen_vert_id = nil return end if self.change_dir_time < time_global() then self.change_dir_time = time_global() + math.random( 1000, 2000 ) local ang = math.rad( math.random( 0, 359 ) ) local pos = self.object:position():add( vector():set( math.cos( ang ), 0, math.sin( ang ) ) ) state_mgr.set_state( self.object, "hide", nil, nil, { look_position = pos } ) end end function action_look_around:finalize() action_base.finalize( self ) end -------------------------------------------------------------------------------------------------------------- class "action_go_to_pos" ( action_base ) function action_go_to_pos:__init( name, storage ) super ( nil, name ) self.st = storage self.t = {} end function action_go_to_pos:initialize() action_base.initialize( self ) if not self.st.last_seen_vert_id then self.st.last_seen_vert_id = self.object:best_enemy():level_vertex_id() end -- self.object:set_node_evaluator () -- self.object:set_path_evaluator () self.object:set_desired_direction () self.object:set_desired_position () self.object:set_detail_path_type ( move.line ) self.object:set_path_type ( game_object.level_path ) state_mgr.set_state( self.object, "assault" ) self.cached_id = -1 end function action_go_to_pos:execute() action_base.execute( self ) if self.st.last_seen_vert_id ~= self.cached_id then self.cached_id = self.st.last_seen_vert_id self.st.last_seen_vert_id = utils.send_to_nearest_accessible_vertex( self.object, self.cached_id ) end end function action_go_to_pos:finalize() action_base.finalize( self ) end -------------------------------------------------------------------------------------------------------------- function add_to_binder( npc, ini, st, planner ) --[[ planner:add_evaluator( xr_evaluators_id.combat_monolith_base, evaluator_combat_monolith( "combat_monolith", st ) ) local action = action_zombie_shoot( "action_zombie_shoot", st ) action:add_precondition( world_property( xr_evaluators_id.combat_monolith_base, true ) ) action:add_effect ( world_property( stalker_ids.property_enemy, false ) ) planner:add_action( xr_actions_id.combat_monolith_base, action )]] planner:add_evaluator( prop_enable, evaluator_combat_monolith( "combat_monolith", st ) ) planner:add_evaluator( prop_see, evaluator_see ( "combat_monolith_see", st ) ) planner:add_evaluator( prop_close, evaluator_close ( "combat_monolith_close", st ) ) planner:add_evaluator( prop_on_pos, evaluator_on_pos ( "combat_monolith_on_pos", st ) ) local action = action_fight_close( "combat_monolith_fight_close", st ) action:add_precondition( world_property( stalker_ids.property_alive, true ) ) action:add_precondition( world_property( stalker_ids.property_enemy, true ) ) action:add_precondition( world_property( stalker_ids.property_anomaly, false ) ) action:add_precondition( world_property( xr_evaluators_id.script_combat, true ) ) action:add_precondition( world_property( prop_enable, true ) ) action:add_precondition( world_property( prop_see, true ) ) action:add_precondition( world_property( prop_close, true ) ) action:add_effect ( world_property( stalker_ids.property_enemy, false ) ) planner:add_action( act_fight_close, action ) -- подписываем один, работает во всех! xr_logic.subscribe_action_for_events( npc, st, action ) action = action_fight_far( "combat_monolith_fight_far", st ) action:add_precondition( world_property( stalker_ids.property_anomaly, false ) ) action:add_precondition( world_property( prop_close, false ) ) action:add_precondition( world_property( prop_see, true ) ) action:add_effect ( world_property( prop_close, true ) ) planner:add_action( act_fight_far, action ) action = action_look_around( "combat_monolith_look_around", st ) action:add_precondition( world_property( stalker_ids.property_anomaly, false ) ) action:add_precondition( world_property( prop_on_pos, true ) ) action:add_precondition( world_property( prop_see, false ) ) action:add_effect ( world_property( prop_see, true ) ) planner:add_action( act_look_around, action ) action = action_go_to_pos( "combat_monolith_go_to_pos", st ) action:add_precondition( world_property( stalker_ids.property_anomaly, false ) ) action:add_precondition( world_property( prop_on_pos, false ) ) action:add_effect ( world_property( prop_on_pos, true ) ) planner:add_action( act_go_to_pos, action ) end