class "fake_monster" function fake_monster:__init( obj , storage) self.object = obj self.st = storage self.is_actor_inside = nil end function fake_monster:reset_scheme() printf("_bp: sr_idle: fake_monster:reset_scheme: self.object:name()='%s'", self.object:name()) self.st.idle_end = 0 self.st.signals = {} self.is_actor_inside = false self.snd_obj = nil self.final_action = false self.appear_snd = sound_object("monsters\\boar\\boar_swamp_appear_1") self.idle_state = false self.path_name = nil self.monster_obj = nil end function fake_monster:update( delta ) local actor = db.actor if self.idle_state then if self.st.idle_end <= game.time() then self.idle_state = false printf("idle state --- false") end return end -- Если не указана секция монстра, то считаем что зонка должна сработать на вход НПС и отыграть только звук. -- if self.st.monster == nil and xr_motivator.bloodsucker_zone_enter[self.object:id()] ~= nil and self.is_actor_inside == false then -- self.is_actor_inside = true -- self:on_enter() -- end if self.is_actor_inside == nil and self.st.monster ~= nil then self.is_actor_inside = self.object:inside( actor:position() ) return end if self.object:inside( actor:position() ) then if not self.is_actor_inside then self:on_enter( actor ) self.is_actor_inside = true end end if self.final_action and (db.storage[self.monster.id] == nil or self.monster_obj:position():distance_to(self.st.path:point(self.st.path:count()-1)) <= 1) then if db.storage[self.monster.id] ~= nil then xr_logic.mob_release(self.monster_obj) end alife():release(self.monster,true) self.monster = nil self.monster_obj = nil self.final_action = false self.idle_state = true self.st.idle_end = game.time() + self.st.idle printf("idle state --- true") self.is_actor_inside = false self:reset_path() return end if self.is_actor_inside == true and self.monster == nil then local target_pos = vector():set(self.current) target_pos:mad(self.dir, self.st.sound_slide_vel * delta / 1000) if target_pos:distance_to(self.current) > self.current:distance_to(self.target) then self.cur_point = self:next_point() self:set_positions() else self.current = vector():set(target_pos) end self.snd_obj = xr_sound.set_sound_play( self.object:id(), self.st.snd_obj) printf("play_sound_obj") if self.snd_obj and self.snd_obj:playing() then self.snd_obj:set_position(self.current) end elseif self.monster_obj == nil and self.monster ~= nil and db.storage[self.monster.id] ~= nil and not self.final_action then self.monster_obj = db.storage[self.monster.id].object xr_logic.mob_capture(self.monster_obj, true) action(self.monster_obj, move(move.run_fwd, self.st.path:point(self.st.path:count()-1)),cond(cond.move_end)) printf("added action RUN to %s(%s)", self.path_name, tostring(self.st.path:count()-1)) self.final_action = true end xr_logic.try_switch_to_another_section( self.object, self.st, db.actor ) end function fake_monster:on_enter() self:reset_path() self:set_positions() end function fake_monster:reset_path() self.cur_point = 0 local path_name_new = self.path_name local path_count = #self.st.path_table if path_count == 1 then self.path_name = self.st.path_table[1] self.st.path = patrol(self.path_name) return end while self.path_name == path_name_new do path_name_new = self.st.path_table[math.random(1,path_count)] end self.path_name = path_name_new self.st.path = patrol(self.path_name) printf("path_name : %s", self.path_name) end function fake_monster:next_point() if self.cur_point+1 < self.st.path:count() then return self.cur_point+1 else return 0 end end function fake_monster:set_positions() if (self:next_point() == 0) then if self.monster == nil and self.st.monster ~= nil then self.monster = alife():create( self.st.monster, self.current, self.object:level_vertex_id(), self.object:game_vertex_id()) self.monster.sim_forced_online = true end self.appear_snd:play_at_pos( db.actor, self.current, 0, sound_object.s3d) if self.snd_obj ~= nil then self.snd_obj:stop() end self:reset_path() end self.current = self.st.path:point(self.cur_point) self.target = self.st.path:point(self:next_point()) self.dir = vector():sub(self.target, self.current):normalize() end --------------------------------------------------------------------------------------------------------------------- function add_to_binder( npc, ini, scheme, section, storage ) printf("DEBUG: add_to_binder: scheme='%s', section='%s'", scheme, section) local new_action = fake_monster(npc, storage) -- Зарегистрировать все actions, в которых должен быть вызван метод reset_scheme при изменении настроек схемы: xr_logic.subscribe_action_for_events( npc, storage, new_action ) end function set_scheme( obj, ini, scheme, section, gulag_name ) local st = xr_logic.assign_storage_and_bind( obj, ini, scheme, section ) st.logic = xr_logic.cfg_get_switch_conditions( ini, section, obj ) st.snd_obj = utils.cfg_get_string( ini, section, "snd", obj, false, "", nil ) st.delay = utils.cfg_get_number( ini, section, "delay", obj, false, 0 ) st.idle = utils.cfg_get_number( ini, section, "idle", obj, false, 30 ) * 10000 -- секунды->мс local path = utils.cfg_get_string( ini, section, "sound_path", obj, false, "", nil ) st.path_table = parse_names(path) st.monster = utils.cfg_get_string( ini, section, "monster_section", obj, false, "", nil) st.sound_slide_vel = utils.cfg_get_number(ini, section, "slide_velocity", obj, false, 7) end