---------------------------------------------------------------------------------------------------- -- Remark ---------------------------------------------------------------------------------------------------- local state_initial = 0 local state_animation = 1 local state_sound = 2 local state_finish = 3 local body_state_free = 0 local body_state_danger = 1 --------------------------------------------------------------------------------------------------------------------- class "evaluator_need_remark" (property_evaluator) function evaluator_need_remark:__init(storage, name) super(nil, name) self.st = storage end function evaluator_need_remark:evaluate() return xr_logic.is_active(self.object, self.st) end ---------------------------------------------------------------------------------------------------------------------- class "action_remark_activity" (action_base) function action_remark_activity:__init (npc_name, action_name, storage) super(nil, action_name) self.st = storage end function action_remark_activity:initialize() action_base.initialize(self) self.object:set_desired_position() self.object:set_desired_direction() -- xr_sound.set_sound(self.object, nil) end function action_remark_activity:activate_scheme() self.st.signals = {} self.sound_end_signalled = false self.action_end_signalled = false self.anim_end_signalled = false -- Определим нужно ли нам отыгрывать анимацию/поворачиваться на объект. self.anim_scheduled = true -- Определим нужно ли нам отыгрывать отдельно звук после поворота. if self.st.snd_anim_sync == false and self.st.snd ~= nil then self.snd_scheduled = true else self.snd_scheduled = false end self.snd_started = false -- Задаем стартовое состояние self.state = state_initial self.tips_sound = nil end function action_remark_activity:get_target() local look_tbl = {} --' Если таргет не проинициализирован, то запускаем инициализатор. self.st.target_position, self.st.target_id, self.st.target_init = init_target(self.object, self.st.target) if self.st.target_init == false then --printf("target_is_ni!!!l") return nil end if self.st.target_id then look_tbl.look_object = level.object_by_id(self.st.target_id) end if self.st.target_position then look_tbl.look_position = self.st.target_position end --printf("look_table") --print_table(look_tbl) return look_tbl end function action_remark_activity:time_callback() --printf("TIME CALLBACK CALLED") self.state = state_sound self:update() end function action_remark_activity:update() --' 1. Мы должны повернуться на объект. --printf("REMARK: [%s] state[%s]", self.object:name(), self.state) if self.state == state_initial then local cb = { obj = self, func = self.time_callback } local target = self:get_target() if target == nil then local anim = xr_logic.pick_section_from_condlist(db.actor, self.object, self.st.anim) state_mgr.set_state(self.object, anim, cb, 0) self.state = state_animation return end local anim = xr_logic.pick_section_from_condlist(db.actor, self.object, self.st.anim) state_mgr.set_state(self.object, anim, cb, 0, target) self.state = state_animation --' Ожидание колбека от стейтменеджера elseif self.state == state_animation then --' 2. Мы должны отыграть фразу. elseif self.state == state_sound then if self.snd_scheduled == true then self.snd_started = true xr_sound.set_sound_play(self.object:id(), self.st.snd) end --' Должны выдать сигнал anim_end if self.anim_end_signalled == false then self.anim_end_signalled = true self.st.signals["anim_end"] = true end if self.st.signals["sound_end"] == true or self.st.signals["theme_end"] == true then --printf("SOUND_END signalled!!!") if self.sound_end_signalled == false then self.sound_end_signalled = true end end if self.sound_end_signalled == true and self.anim_end_signalled == true then if self.action_end_signalled == false then --printf("ACTION_END signalled!!!") self.st.signals["action_end"] = true self.action_end_signalled = true end end --' Нужно выдать связанный типс. if self.st.tips_id ~= nil then self.tips_sound = news_manager.send_tip_nosound(db.actor, self.st.tips_id, self.st.sender) if self.tips_sound ~= nil then --' Играем звук забитый self.tips_sound:play(db.actor, 0, sound_object.s2d) end end end end function action_remark_activity:execute() action_base.execute(self) self:update() end function action_remark_activity:finalize() if self.tips_sound ~= nil then self.tips_sound:stop() end action_base.finalize(self) end ---------------------------------------------------------------------------------------------------------------------- --remark binder ---------------------------------------------------------------------------------------------------------------------- function add_to_binder(npc, ini, scheme, section, storage) printf("DEBUG: add_to_binder [%s]: scheme='%s', section='%s'", npc:name(), scheme, section) local operators = {} local properties = {} local manager = npc:motivation_action_manager() properties["event"] = xr_evaluators_id.reaction properties["need_remark"] = xr_evaluators_id.zmey_remark_base + 1 properties["state_mgr_logic_active"] = xr_evaluators_id.state_mgr + 4 operators["action_remark"] = xr_actions_id.zmey_remark_base + 1 -- evaluators manager:add_evaluator(properties["need_remark"], this.evaluator_need_remark(storage, "remark_need_remark")) local new_action = this.action_remark_activity(npc, "action_remark_activity", 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(properties["need_remark"], true)) xr_motivator.addCommonPrecondition(new_action) new_action:add_effect(world_property(properties["need_remark"], false)) new_action:add_effect (world_property(properties["state_mgr_logic_active"], false)) manager:add_action(operators["action_remark"], 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_remark"], false)) end -- Включение схемы function set_scheme(npc, ini, scheme, section, gulag_name) printf("DEBUG: set_scheme: scheme='%s', section='%s'", scheme, section) local st = xr_logic.assign_storage_and_bind(npc, ini, scheme, section) printf("DEBUG: set_scheme: storage assigned") st.logic = xr_logic.cfg_get_switch_conditions(ini, section, npc) st.snd_anim_sync = utils.cfg_get_bool(ini, section, "snd_anim_sync", npc, false) st.snd = utils.cfg_get_string(ini, section, "snd", npc, false, "", nil) st.anim = xr_logic.parse_condlist(npc, "anim", "anim", utils.cfg_get_string(ini, section, "anim", npc, false, "", "wait")) st.tips_id = utils.cfg_get_string(ini, section, "tips", npc, false, "") if st.tips_id then st.sender = utils.cfg_get_string(ini, section, "tips_sender", npc, false, "") end st.target = utils.cfg_get_string (ini, section, "target", npc, false, "", "nil") st.target_id = nil st.target_position = nil end local function instruction(obj, target_str) abort("\nWrong target field for object [%s] in section [%s]!!!\n".. "Field [target] supports following:\n".. " target = story | actor or story_id\n".. " target = path | patrol_path, point_id\n".. " target = job | job_section, smart_name\n".. "Your target field:\n".. " target = %s", obj:name(), db.storage[obj:id()].active_section, target_str) end function init_target(obj, target_str) local function parse_target(target_str) local pos = string.find(target_str, ",") if pos then return string.sub(target_str, 1, pos - 1), string.sub(target_str, pos + 1) else return target_str, nil end end local function parse_type(target_str) local pos = string.find(target_str, "|") if pos == nil then instruction(obj, target_str) end local target_type, target = string.sub(target_str, 1, pos - 1), string.sub(target_str, pos + 1) if target == nil or target == "" or target_type == nil or target_type == "" then instruction(obj, target_str) end return target_type, target end local target_pos, target_id, target_initialized = nil, nil, false if target_str == "nil" then return target_pos, target_id, target_initialized elseif target_str == nil then instruction(obj, "") end local target_type, target = parse_type(target_str) if target_type == "story" then local story_id = parse_target(target) target_id = get_story_object_id(story_id) target_initialized = true elseif target_type == "path" then local path, point = parse_target(target) point = tonumber(point) if point then target_pos = patrol(path):point(point) target_initialized = true end elseif target_type == "job" then local job, gulag = parse_target(target) if gulag then gulag = xr_gulag.get_gulag_by_name(gulag) else gulag = xr_gulag.get_npc_smart(npc) end target_id = gulag:idNPCOnJob(job) target_initialized = (target_id ~= nil) and true else instruction(obj, target_str) end return target_pos, target_id, target_initialized end