Перейти к контенту

Скриптование


Svoboда

Рекомендуемые сообщения

Доброго времени суток!

Делал квест, неудачным завершением которого, была бы полная зачистка военными лагеря новичков на Кордоне.

Столкнулся с проблемой: нпс не хотят заходить в некоторые дома дальше крыльца (пути много раз менял и перепроверял). Судя по имеющейся у меня информации - там нет ai-сетки. Возможно ли их туда провести, не прибегая к редактированию уровня? Видел, как некоторые люди сталкивались с "противоположной" проблемой: нпс ходили через стены, вроде как при указании неправильных level- и game- vertex'ов.

Заранее спасибо!

Поделиться этим сообщением


Ссылка на сообщение

Доброго времени суток!

Переписываю схему heli hunter: в функции evaluator_shoot:evaluate() делаю проверку на огневую мощь НПС, при выполнении условия отправляю их в укрытие.

if self.fire_power < 3 then
    self.object:set_detail_path_type(move.line)
    self.object:set_path_type(game_object.level_path)
    local hide,lvid = nearest_hide(self.object)
    utils.send_to_nearest_accessible_vertex(self.object,lvid)
    state_mgr.set_state(self.object,"sprint")
    return false
end

--[[------------------------------------------------------------------------------------------------------------------
Схема "Охотник за вертолётами"
Чугай Александр
--------------------------------------------------------------------------------------------------------------------]]

local def_attack_dist = 200 -- расстояние, на котором вертолёт может быть атакован
local def_actor_dist  = 50  -- расстояние, на котором игрок может быть атакован

function get_nearest_heli(npc_position, attack_dist_sqr)
--    print_table(db.heli)

    local heli = nil

    for k,v in pairs(db.heli) do
        if v:position():distance_to_sqr(npc_position) <= attack_dist_sqr and
           (heli == nil or
           v:position():distance_to_sqr(npc_position) < heli:position():distance_to_sqr(npc_position))
        then
            heli = v
        end
    end

    return heli
end
---------------------------------------------------------------------------------------------------------------------
-- Эвалуатор свойства "можно пострелять по вертолёту"
---------------------------------------------------------------------------------------------------------------------
local overrides

class "evaluator_shoot" ( property_evaluator )

function evaluator_shoot:__init( name, a ) super( nil, name )
    self.a = a
end

function evaluator_shoot:evaluate()

        if self.delay and self.delay >= time_global() then
            return false
        end

        self.a.heli = get_nearest_heli(self.object:position(), self.a.attack_dist_sqr)
        self.fire_power = heli_target.get_target_priority(self.object)
        
        if self.a.heli == nil then
            self.delay = time_global() + 500
            return false
        end
        
        --проверка на группировку
        if db.storage[self.a.heli:id()].community ~= nil and (db.storage[self.a.heli:id()].community == self.object:character_community()) then
            return false
        end

        --Проверка на огневую мощь
        if self.fire_power < 3 then
            self.object:set_detail_path_type(move.line)
            self.object:set_path_type(game_object.level_path)
            hide,lvid,dist = blowout_scheme.nearest_hide(self.object)
            utils.send_to_nearest_accessible_vertex(self.object,lvid)
            state_mgr.set_state(self.object,"sprint")
            return false
        end

        -- Проверка на то, что вертолет еще живой.
        if not bind_heli.is_heli_alive(self.a.heli) then
            self.a.heli = nil
            return false
        end

        -- проверка не потерялся ли вертолет.
--        if db.heli[self.a.heli:id()] ~= nil and
--        printf( "dist=%d", self.a.heli:position():distance_to_sqr(self.object:position()) )
        if self.a.heli:position():distance_to_sqr(self.object:position()) > self.a.attack_dist_sqr then
            self.a.heli = nil
            return false
        end

        -- Проверка на то, что враг-игрок не подошел слишком близко
        local best_enemy = self.object:best_enemy()
        if best_enemy and
           best_enemy:id() == db.actor:id()
        then
            if db.actor:position():distance_to_sqr(self.object:position()) < self.a.attack_actor_sqr then
                return false
            end
        end

        -- Проверка на то, что денжер-игрок не подошел слишком близко
        local best_danger = self.object:best_danger()
        if best_danger then
           local bd_object = best_danger:object()
           if bd_object ~= nil and
              bd_object:id() == db.actor:id()
           then
                if best_danger:position():distance_to_sqr(self.object:position()) < self.a.attack_actor_sqr then
                    return false
                end
           end
        end
        return true
end

----------------------------------------------------------------------------------------------------------------------
-- Действие "стрелять по вертолёту"
----------------------------------------------------------------------------------------------------------------------
class "action_shoot" ( action_base )

function action_shoot:__init( name, a )  super ( nil, name )
    self.a = a
end

function action_shoot:initialize()
    action_base.initialize( self )

end

function action_shoot:execute()
    action_base.execute( self )
    
        state_mgr.set_state( self.object, "threat_fire", nil, nil,
                         {look_object = self.a.heli}, nil, nil, {yaw_delta=10} )    

end

function action_shoot:finalize()
    action_base.finalize( self )
    --self.fire_power = nil
    self.camp = nil
    self.need_cover = nil
self.object:movement_enabled(true)
end

----------------------------------------------------------------------------------------------------------------------

function add_to_binder( npc, ini, scheme, section, storage )
    printf( "DEBUG: add_to_binder: scheme='%s'", scheme )

    local manager = npc:motivation_action_manager()

    manager:add_evaluator( xr_evaluators_id.chugai_heli_hunter_base, evaluator_shoot( "heli_hunter", storage ) )

    local action = this.action_shoot( "action_shoot", storage )
    action:add_precondition( world_property(stalker_ids.property_alive,               true  ) )
    action:add_precondition( world_property(xr_evaluators_id.chugai_heli_hunter_base, true  ) )
    action:add_effect      ( world_property(xr_evaluators_id.chugai_heli_hunter_base, false ) )
    manager:add_action( xr_actions_id.chugai_heli_hunter_base, action )

    action = manager:action( xr_actions_id.alife )
    action:add_precondition( world_property( xr_evaluators_id.chugai_heli_hunter_base, false ) )

    action = manager:action( stalker_ids.action_combat_planner )
    action:add_precondition( world_property( xr_evaluators_id.chugai_heli_hunter_base, false ) )

    action = manager:action( stalker_ids.action_danger_planner )
    action:add_precondition( world_property( xr_evaluators_id.chugai_heli_hunter_base, false ) )
end

function set_scheme( npc, ini, scheme, section )
    printf( "DEBUG: set_scheme: scheme='%s' section='%s'", scheme, utils.to_str(section) )

    local a = xr_logic.assign_storage_and_bind( npc, ini, scheme, section )

    a.attack_dist_sqr = math.pow( utils.cfg_get_number( ini, section, "dist", npc, false, def_attack_dist ), 2 )
    a.attack_actor_sqr = math.pow( utils.cfg_get_number( ini, section, "actor_dist", npc, false, def_actor_dist ), 2 )
    a.heli = nil
    a.enabled = true
end

function disable_scheme(npc, scheme)
    local st = db.storage[npc:id()][scheme]
    if st then
        st.enabled = false
    end
end

 

 

НПС бегут в укрытие, но когда вертолет улетает\взрывается НПС так и остаются там стоять пока с ними не поговоришь.

Как вернуть НПС под свою изначальную логику (или что я делаю неправильно)?

 

Поделиться этим сообщением


Ссылка на сообщение

Пытаюсь подредактировать схему heli hunter.

В своем предыдущем посте я пытался вызвать реакцию НПС на вертолет прямо из эвалуатора. Т.к. это неправильно - перенес действия в action: если раньше они хотя бы убегали, то теперь стеляют по вертолету вообще игнорируя условия:

--[[------------------------------------------------------------------------------------------------------------------
Схема "Охотник за вертолётами"
Чугай Александр
--------------------------------------------------------------------------------------------------------------------]]

local def_attack_dist = 200 -- расстояние, на котором вертолёт может быть атакован
local def_actor_dist  = 50  -- расстояние, на котором игрок может быть атакован

function get_nearest_heli(npc_position, attack_dist_sqr)
--    print_table(db.heli)

    local heli = nil

    for k,v in pairs(db.heli) do
        if v:position():distance_to_sqr(npc_position) <= attack_dist_sqr and
           (heli == nil or
           v:position():distance_to_sqr(npc_position) < heli:position():distance_to_sqr(npc_position))
        then
            heli = v
        end
    end

    return heli
end
---------------------------------------------------------------------------------------------------------------------
-- Эвалуатор свойства "можно пострелять по вертолёту"
---------------------------------------------------------------------------------------------------------------------
local overrides

class "evaluator_shoot" ( property_evaluator )

function evaluator_shoot:__init( name, a ) super( nil, name )
    self.a = a
end

function evaluator_shoot:evaluate()


        if self.delay and self.delay >= time_global() then
            return false
        end

        self.a.heli = get_nearest_heli(self.object:position(), self.a.attack_dist_sqr)

        --провека на существование вертолета
        if self.a.heli == nil then
            self.delay = time_global() + 500
            self.hide = nil
            return false
        end
        
        --проверка на группировку
        if db.storage[self.a.heli:id()].community ~= nil and (db.storage[self.a.heli:id()].community == self.object:character_community()) then
            return false
        end

        -- проверка на то, что вертолет еще живой.
        if not bind_heli.is_heli_alive(self.a.heli) then
            self.a.heli = nil
            return false
        end


        self.fire_power = heli_target.get_target_priority(self.object)

        --Проверка на огневую мощь
        if self.fire_power < 3 then
            self.hide = true
            --return false
        end

        -- проверка не потерялся ли вертолет.
--        if db.heli[self.a.heli:id()] ~= nil and
--        printf( "dist=%d", self.a.heli:position():distance_to_sqr(self.object:position()) )
        if self.a.heli:position():distance_to_sqr(self.object:position()) > self.a.attack_dist_sqr then
            self.a.heli = nil
            return false
        end

        -- Проверка на то, что враг-игрок не подошел слишком близко
        local best_enemy = self.object:best_enemy()
        if best_enemy and
           best_enemy:id() == db.actor:id()
        then
            if db.actor:position():distance_to_sqr(self.object:position()) < self.a.attack_actor_sqr then
                return false
            end
        end

        -- Проверка на то, что денжер-игрок не подошел слишком близко
        local best_danger = self.object:best_danger()
        if best_danger then
           local bd_object = best_danger:object()
           if bd_object ~= nil and
              bd_object:id() == db.actor:id()
           then
                if best_danger:position():distance_to_sqr(self.object:position()) < self.a.attack_actor_sqr then
                    return false
                end
           end
        end
        
        return true
end

----------------------------------------------------------------------------------------------------------------------
-- Действие "стрелять по вертолёту"
----------------------------------------------------------------------------------------------------------------------
class "action_shoot" ( action_base )

function action_shoot:__init( name, a )  super ( nil, name )
    self.a = a
end

function action_shoot:initialize()
    action_base.initialize( self )

end

function action_shoot:execute()
    action_base.execute( self )
    
    if self.hide == true then
        self.object:set_detail_path_type(move.line)
        self.object:set_path_type(game_object.level_path)
        hide,lvid,dist = blowout_scheme.nearest_hide(self.object)
        utils.send_to_nearest_accessible_vertex(self.object,lvid)
        state_mgr.set_state(self.object,"sprint")
    else
        state_mgr.set_state( self.object, "threat_fire", nil, nil,
                         {look_object = self.a.heli}, nil, nil, {yaw_delta=10} )    
    end

end

function action_shoot:finalize()
    action_base.finalize( self )
    self.fire_power = nil
    self.camp = nil
    self.hide = nil
self.object:movement_enabled(true)
end

----------------------------------------------------------------------------------------------------------------------

function add_to_binder( npc, ini, scheme, section, storage )
    printf( "DEBUG: add_to_binder: scheme='%s'", scheme )

    local manager = npc:motivation_action_manager()
    manager:add_evaluator( xr_evaluators_id.chugai_heli_hunter_base, evaluator_shoot( "heli_hunter", storage ) )

    local action = this.action_shoot( "action_shoot", storage )
    action:add_precondition( world_property(stalker_ids.property_alive,               true  ) )
    action:add_precondition( world_property(xr_evaluators_id.chugai_heli_hunter_base, true  ) )
    action:add_effect      ( world_property(xr_evaluators_id.chugai_heli_hunter_base, false ) )
    manager:add_action( xr_actions_id.chugai_heli_hunter_base, action )

    action = manager:action( xr_actions_id.alife )
    action:add_precondition( world_property( xr_evaluators_id.chugai_heli_hunter_base, false ) )

    action = manager:action( stalker_ids.action_combat_planner )
    action:add_precondition( world_property( xr_evaluators_id.chugai_heli_hunter_base, false ) )

    action = manager:action( stalker_ids.action_danger_planner )
    action:add_precondition( world_property( xr_evaluators_id.chugai_heli_hunter_base, false ) )
end

function set_scheme( npc, ini, scheme, section )
    printf( "DEBUG: set_scheme: scheme='%s' section='%s'", scheme, utils.to_str(section) )

    local a = xr_logic.assign_storage_and_bind( npc, ini, scheme, section )

    a.attack_dist_sqr = math.pow( utils.cfg_get_number( ini, section, "dist", npc, false, def_attack_dist ), 2 )
    a.attack_actor_sqr = math.pow( utils.cfg_get_number( ini, section, "actor_dist", npc, false, def_actor_dist ), 2 )
    a.heli = nil
    a.enabled = true
end

function disable_scheme(npc, scheme)
    local st = db.storage[npc:id()][scheme]
    if st then
        st.enabled = false
    end
end

function get_target_priority(obj)
    if not obj then return 0 end
    --qqq(obj:section())
    local prior = 1
    if IsMonster(obj) then
    --    qqq("monster")
        prior = 1
    elseif IsStalker(obj) then -- максимум - 5
        local wpn = obj:item_in_slot(obj:active_slot())
        if wpn then
            local ammo, fm
            if system_ini():line_exist(wpn:section(), "ammo_class") then
                ammo = system_ini():r_string(wpn:section(), "ammo_class")
                if (string.find(ammo, "9x18") -- пистолетные патроны
                    or string.find(ammo, "9x19")
                    or string.find(ammo, "7.62x25")
                    or string.find(ammo, "11.43x23")
                    or string.find(ammo, "357")
                    or string.find(ammo, "samopal") --  + патроны к самопалу
                    or string.find(ammo, "bolt") --  + арбалетные болты
                    or string.find(ammo, "12x7")) --  + патроны для дробовиков
                    then
                    prior = prior + 1
                elseif (string.find(ammo, "5.45x39") -- промежуточные патроны
                    or string.find(ammo, "5.56x45") 
                    or string.find(ammo, "7.62x39")
                    or string.find(ammo, "9x39"))
                    then
                    prior = prior + 2
                elseif (string.find(ammo, "7.62x51") -- винтовочные патроны
                    or string.find(ammo, "7.62x54")
                    or string.find(ammo, "7.92x75"))
                    then
                    prior = prior + 3
                else
                    prior = prior + 4
                end
            end
            if system_ini():line_exist(wpn:section(), "fire_modes") then
                fm = system_ini():r_string(wpn:section(), "fire_modes")
                if string.sub(fm,-2,-1) == "-1" then
                    prior = prior + 1 -- автоматическое оружие - приоритет цели выше на 1
                end
            end
        --qqq(wpn:section())
        end
    elseif string.find(obj:name(),"btr") then
        prior = 6
    elseif (string.find(obj:section(),"helicopter") or string.find(obj:section(),"mi2")) then
        prior = 7
    end
    
    --qqq(prior)
    return prior
end

 

Или, если я неправильно выбрал путь решения проблемы - подскажите, как переключить НПС на схему выброса (без выброса) при виде вертолета, если у них нечем в него стрелять, т.е. чтобы НПС вели себя точно также как при выбросе, завидев вертолет?

 

Заранее спасибо!

 

Используйте тэги

 для вывода участков с кодами, дабы сохранялось форматирование (отступы) и не искажались иные символы

--/ Artos

Изменено пользователем Artos

Поделиться этим сообщением


Ссылка на сообщение
×
×
  • Создать...