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

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

Делаю схему поведения для ЗП-COC. НПС доходит до объекта и играет анимацию:

Скрытый текст

class "need" (property_evaluator)

function need:__init(storage, name, npc) super(nil, name)
	self.object = npc
end

function need:evaluate()
	return self.object:alive()
end

class "on_need_point" (property_evaluator)

function on_need_point:__init(storage, name, npc) super(nil, name)
	self.st = storage
	self.object = npc
end

function on_need_point:evaluate()
	return self.st.purpose.position:distance_to_sqr(self.object:position()) < 6
end

class "go_target" (action_base)

function go_target:__init (npc, action_name, storage) super(nil, action_name)
	self.st = storage
	self.object = npc
end

function go_target:initialize()
	action_base.initialize(self)
	
	self.st.dqAnim = false
	self.object:set_desired_position()
	self.object:set_desired_direction()
	
	self.object:inactualize_patrol_path		()
	
	self.object:set_desired_direction   	()
	self.object:set_movement_selection_type	(game_object.alifeMovementTypeMask)
	--self.object:set_item					(object.idle, self.object:best_weapon())
	self.object:set_body_state				(move.standing)
	self.object:set_detail_path_type    	( move.line )
	self.object:set_mental_state			(anim.free) --free
	self.object:set_movement_type			(move.run)
	
	--self.object:set_path_type           	( game_object.game_path )
	if game_graph():vertex(self.st.purpose.m_game_vertex_id):level_id() == game_graph():vertex(self.object:game_vertex_id()):level_id() then
		self.object:set_path_type(game_object.level_path)
		utils.send_to_nearest_accessible_vertex(self.object, self.st.purpose.m_level_vertex_id, "xr_mytest:1")
		self.object:set_desired_position(self.st.purpose.position)
		get_console():execute(1)
	else
		self.object:set_dest_game_vertex_id		( self.st.purpose.m_game_vertex_id)
		self.object:set_path_type ( game_object.game_path )
		get_console():execute(2)
	end
	self.object:set_sight					(look.path_dir,nil,0)
end

function go_target:execute()
	action_base.execute(self)
	
end

function go_target:finalize()
	action_base.finalize(self)
end


function go_target:activate_scheme()
	action_base.initialize(self)
end

class "wait_action"  (action_base)

function wait_action:__init (npc, action_name, storage) super(nil, action_name)
	self.st = storage
	self.object = npc
	self.st.dqAnim = false
end

local anm, cb
function wait_action:initialize()
	action_base.initialize(self)
	get_console():execute("wait_action")
	
	self.object:set_desired_position()
	self.object:set_desired_direction()
	
	cb = { obj = self, func = self.time_callback }
	anm = 'sit_knee'--xr_logic.pick_section_from_condlist(db.actor, self.object, self.st.anm)
	state_mgr.set_state(self.object, anm, cb, 0, {look_position = self.st.purpose.position})
end

function wait_action:time_callback()
	self.st.dqAnim = true
end

function wait_action:execute ()
	action_base.execute(self)
	
	
end

class "end_anim" (property_evaluator)

function end_anim:__init(storage, name) super(nil, name)
	self.st = storage
	self.st.dqAnim = false
end

function end_anim:evaluate()
	return --self.st.dqAnim
end


function add_to_binder(npc, ini, scheme, section, storage)
	local operators	= {}
	local properties  = {}

	local manager = npc:motivation_action_manager()
	
	operators["act2point"] = xr_evaluators_id.zmey_remark_base + 2
	operators["anims"] = xr_evaluators_id.zmey_remark_base + 3
	
	properties["has"] = xr_actions_id.zmey_remark_base + 4
	properties["at_point"]  = xr_actions_id.zmey_remark_base + 5
	properties["anim_end"] = xr_actions_id.zmey_remark_base + 6
		 -- evaluators
	manager:add_evaluator(properties["has"], this.need(storage, "has_uniq", npc))
	manager:add_evaluator(properties["at_point"], this.on_need_point(storage, "on_need_point_uniq", npc))
	manager:add_evaluator(properties["anim_end"], this.end_anim(storage, "anim_end"))

	local new_action2 = this.wait_action(npc, "wait_action", storage)
	new_action2:add_precondition(world_property(stalker_ids.property_alive, true))
	new_action2:add_precondition(world_property(stalker_ids.property_danger,false))
	new_action2:add_precondition(world_property(stalker_ids.property_enemy, false))
	new_action2:add_precondition(world_property(stalker_ids.property_anomaly,false))
	modules.add_common_precondition(scheme, new_action2)
	
	new_action2:add_precondition(world_property(properties["has"], true))
	new_action2:add_precondition(world_property(properties["at_point"], true))
	new_action2:add_precondition(world_property(properties["anim_end"], false))
	new_action2:add_effect (world_property(properties["anim_end"], true))
	manager:add_action(operators["anims"], new_action2)
	
	local new_action = this.go_target(npc, "go_target", 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))
	modules.add_common_precondition(scheme, new_action)
	
	new_action:add_precondition(world_property(properties["has"], true))
	new_action:add_precondition(world_property(properties["at_point"], false))
	new_action:add_effect (world_property(properties["at_point"], true))
	manager:add_action(operators["act2point"], new_action)
	
	xr_logic.subscribe_action_for_events(npc, storage, new_action2)
	
	local action = manager:action(stalker_ids.action_alife_planner)
	action:add_precondition(world_property(properties["anim_end"], true))
end

function set_scheme(npc, sobj)
	local st = xr_logic.assign_storage_and_bind(npc, false, "pointer", 'pointer')
	
	st.logic     = {}

	st.purpose = sobj

	--[[
	st.snd			= ini:r_string_ex(section,"snd")
	st.anm			= xr_logic.parse_condlist(npc, "anim", "anim", ini:r_string_ex(section,"anim") or "wait")
	st.tips_id		= ini:r_string_ex(section,"tips")
	if st.tips_id then
		st.sender	= ini:r_string_ex(section,"tips_sender")
	end
	st.target = ini:r_string_ex(section,"target") or "nil"
	st.target_id = nil
	st.target_position = nil
	]]
end

 

НПС доходит до точки и стоит. Если самому извне выполнить код из wait_action:initialize(), то НПС перейдет в анимацию. Расставляя выводы в консоль в коде, было выявлено, что экшн wait_action не запускается вообще, хотя условие в on_need_point:evaluate() выполняется в true. Получилось нужное поведение вставляя условие в go_target:execute() из on_need_point:evaluate(). Но хотелось бы хождение и анимацию сделать разными экшенами.

Изменено пользователем Graff46
Ссылка на комментарий

 

Кто в курсе, почему когда в одном скрипте 4 функции, например:

Скрытый текст

function create_level_changer(

...

...

end

function exit_escape_to_garbage1()    
        create_level_changer(11078, db.actor:position(), db.actor:level_vertex_id(), db.actor:game_vertex_id(),     
                        44614,
                        61,
                        vector():set(-208.693, -20.290, -146.893),    
                        vector():set(0.0, 0.0, 0.0),    
                        "l01_escape",
                        1)
end    
function delete_tel()
    local se_obj = alife():object(11078)
    if se_obj then
        alife():release(se_obj, true)
    end

function timer()
    m_timers.quick_timer:aux_cond() 
        self:taction(delete_tel)
end  

Скрытый текст

 [error]Expression    : functor_exists
 [error]Function      : CPhraseScript::Action
 [error]File          : PhraseScript.cpp
 [error]Line          : 214
 [error]Description   : Cannot find <action> script function [provodnik.timer], dialog_id = [teleport_welcome]

То пишет это.

Изменено пользователем Quest_Rider
Ссылка на комментарий

@Quest_Rider, у функции delete_tel отсутствует закрывающий end.

При редактировании скриптов используй редактор с подсветкой синтаксиса.

  • Согласен 3

S.T.A.L.K.E.R. CoP Objects (upd 28.10.24)

Ссылка на комментарий

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

Скрытый текст

for a=0,65534 do
        local obj=level.object_by_id(a)
        if obj then
            if IsStalker(obj) and amk.get_npc_relation(obj,db.actor)=="enemy" then
                local comm  = get_npc_community(obj)
                if comm == "stalker" then
                    ...
                end
            end
        end
    end

 

Здесь могла быть ваша реклама.

Ссылка на комментарий

Есть какой-то простой способ узнать, находится ли актор в укрытии, защищённом от выбросов? И в зависимости от этого вернуть true или false

Кто знает, помогите, подскажите.

Я нашел ответ на свой вопрос: нужно использовать (surge_manager.actor_in_cover())

Ссылка на комментарий

Возможно ли в ТЧ без движковых правок отловить скриптом заклинивание оружия? Мож кто коллбек делал? Хочу прикрутить ругань ГГ из модов для CoC.

  • Нравится 1
Ссылка на комментарий

Вопрос по схемам поведения и симуляции. У меня есть своя схема поведения, в определённый момент я "отключаю" НПС от схемы поведения переведя НПС из скриптового экшена на движковый экшен алайф_планнер, после этого взять НПС под скриптовую схему поведения уже не получится. Мне нужно добиться того, что-бы НПС можно было "отключить" от скриптовй схемы поведения на алайф планировщик, а потом опять, если нужно, взять под скриптовую схему поведения.
Я пробовал, методами класса planner_action, получить ид текущего экшена НПС и удалить этот экшен: После того как я "отключил" НПС от скриптовой схемы поведения, я получил ид текущего экшена НПС, этот ид = 88, 88 - соот-ет иду алайфЭкшенПланнера, я пытаюсь удалить экшен - удаление проходит без ошибок/вылетов, но НПС взять 2раз под скриптовую схему поведения также нельзя и текущий экшен остается алайфПланнером - логично, что удалить единственный экшен, да еще движковый нельзя.

Второй момент: Я решил проверить, какой экшен ид у только, что заспавненного НПС (я ожидал 88), но оказался 363, в луа_хелп под таким ид нету экшенов, вообще нет экшенов с трёхзначными идами.

Третий момент: В ЗП есть класс cast_planner, есть примеры его использования в скриптах игры, но я не понял назначение и функционал этого класса, возможно он мог бы помоч в моем вопросе...

Изменено пользователем Graff46
Ссылка на комментарий
1 час назад, Graff46 сказал:

Второй момент: Я решил проверить, какой экшен ид у только, что заспавненного НПС (я ожидал 88), но оказался 363, в луа_хелп под таким ид нету экшенов, вообще нет экшенов с трёхзначными идами.

Трех и более значные есть в xr_actions_id.script

Ссылка на комментарий

Господа, дня доброго! Помогите пожалуйста

Экспериментирую со скриптовой озвучкой, вот что имеется:

 

Задаём переменной значение, какие звуки играть:

Скрытый текст

snd_name = string.format(
      "characters_voice\\loot\\%s\\loot_%s_%s", comm, good_bad, math.random( 3 )  --первая %s это определение папки с названием фракции, вторая %s это выбор имени звукового файла(good_loot или bad_loot), третья %s - рандом из трёх звуков в папке
    )

 

Далее отрывок кода, заставляющий звук проигрываться:

Скрытый текст

local snd_obj = xr_sound.get_safe_sound_object( snd_name )
  if snd_obj and not snd_obj:playing() then
	amk.send_tip("ЗВУК", "ЗВУК", 2, 15, "common_channel") --проверка что функция до сюда дошла
    snd_obj:play_no_feedback( npc, sound_object.s3d, 0, npc:position(), 1.0 )

 

Всё воспроизводится, но не могу допетрить вот что:

(первый спойлер), как мне скриптово описать выбор соответствующей нужной папки (human_01, human_02, human_03), чтобы голос был соответствующий? Фракция, например, определяется путём npc:character_community(), а папки human_01, human_02, human_03 как сделать?

Ссылка на комментарий

Всем доброго. Вопрос по мародёрству. Есть ли какой скриптовый способ запретить НПСам НЕ брать конкретный предмет с земли и/или трупа/ящика? Или на крайний случай с ящика, не вписывая ID того ящика в исключения amk_offline_alife.script.

Здесь могла быть ваша реклама.

Ссылка на комментарий

Вопрос по схемам поведения и симуляции. У меня есть своя схема поведения, в определённый момент я "отключаю" НПС от схемы поведения переведя НПС из скриптового экшена на движковый экшен алайф_планнер, после этого взять НПС под скриптовую схему поведения уже не получится. Мне нужно добиться того, что-бы НПС можно было "отключить" от скриптовй схемы поведения на алайф планировщик, а потом опять, если нужно, взять под скриптовую схему поведения.
Код схемы поведения: https://pastebin.com/9tUCsxyf

(см. функцию add_to_binder)

Ссылка на комментарий

Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий

Комментарии могут оставлять только зарегистрированные пользователи

Создать аккаунт

Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!

Зарегистрировать новый аккаунт

Войти

Есть аккаунт? Войти.

Войти
  • Недавно просматривали   0 пользователей

    • Ни один зарегистрированный пользователь не просматривает эту страницу.
×
×
  • Создать...