local levels={
  l01_escape = true,
  l02_garbage = true,
  l03_agroprom = true,
  l04_darkvalley = true,
  l05_bar = true,
  l06_rostok = true,
  l07_military = true,
  l08_yantar = true,
  l10_radar = true,
  l11_pripyat = true,
  l12_stancia = true,
  l12_stancia_2 = true
}

function no_suffer_indoor(level_name)
	if levels[level_name] then
		return true
	end
	return false
end

recall_victims = 17

-----------------------------------------------------------------------------------
-- Monster binding
-----------------------------------------------------------------------------------

function bind(obj)
	printf("_bp: monster.bind: name='%s', id='%d'", obj:name(), obj:id())

	-- Для спауна
	--xr_spawner.spawn_client(obj)

	local new_binder = generic_object_binder(obj)
	obj:bind_object(new_binder)
end

------------------------------------------------------------------------------------
class "generic_object_binder" (object_binder)

function generic_object_binder:__init(obj) super(obj)
	self.loaded = false
	self.chtime = 0
end 

function generic_object_binder:reload(section)
	object_binder.reload(self, section)
end

function generic_object_binder:reinit()
	object_binder.reinit(self)

	-- У торговца нет поддержки перемещения
	if self.object:clsid() ~= clsid.script_trader then
		self.object:set_patrol_extrapolate_callback(generic_object_binder.extrapolate_callback, self)
	end

	db.storage[self.object:id()] = { }

	self.st = db.storage[self.object:id()]

	self.object:set_callback(callback.patrol_path_in_point, self.waypoint_callback, self)
	self.object:set_callback(callback.hit,					self.hit_callback,		self)
	self.object:set_callback(callback.death,				self.death_callback,	self)
end

prevent_gulag_registration_for_id=0

function generic_object_binder:update(delta)
	object_binder.update(self, delta)

--	printf("_bp: generic_object_binder: UPDATE [name='%s' time=%d]",
--		self.object:name(), time_global())

	-- Апдейт торговли
	if self.object:clsid() == clsid.script_trader then
		trade_manager.update(self.object)
	end

	if self.object:alive() then
		if self.object:is_talk_enabled() then
			self.object:set_tip_text("character_use")
		else
			self.object:set_tip_text("")
		end
	else
		self.object:set_tip_text_default()
	end

    self:anomaly_evade()
	
	if self.chtime<time_global() then
		self.chtime=time_global()+2000
		if self.object:clsid()==clsid.controller_s and self.object:alive() then
			local npc=self.object:get_enemy()
			if npc then
				if npc:id()~=db.actor:id() and npc:clsid()==clsid.script_stalker and self.object:see(npc) and 
					npc:character_community()~="zombied" and self.object:position():distance_to(npc:position())<60 then
        
          local sobj=alife():object( npc:id() )
					if sobj and sobj.online then
            local zomb=amk.load_table("zombies")
            zomb[sobj.id]={master=self.object:id(),comm=npc:character_community(),gw=npc:goodwill(db.actor)}
            amk.save_table("zombies",zomb)
																		
            npc:set_character_community("zombied",0,0)
            local orgtbl=amk.read_stalker_params(sobj)
            if (not string.find(orgtbl.profile,"_zombi")) then
              orgtbl.profile=orgtbl.profile.."_zombi"
            end
            -- amk.mylog("zombied "..npc:name().." profile "..orgtbl.profile)
            amk.write_stalker_params(orgtbl,sobj)
					end
				end
			end
		end
	end
  
  local blowout=amk.load_variable("blowout",0)
  if blowout==3 and (not self.control_override) and no_suffer_indoor(level.name()) then
    if not self.object:action() then
      -- Захватываем зверушку
      xr_logic.mob_capture(self.object,true)
      self.control_override=true
    end
  elseif self.control_override and blowout==3 then
    if not self.object:action() then
      local snds={sound.take_damage,sound.panic,sound.idle}
      local snd=snds[math.random(1,table.getn(snds))]
      action(self.object, anim(anim.lie_idle, 0), sound(snd), cond(cond.sound_end))
    end
  elseif self.control_override and blowout~=3 then
    -- отпускаем зверушку
    self.control_override=nil
    xr_logic.mob_release(self.object)
	elseif self.st.active_section ~= nil then
		xr_logic.issue_event(self.object, self.st[self.st.active_scheme], "update", delta)
	end
end

function generic_object_binder:anomaly_evade()
  local npc=self.object
  if npc:story_id()==29 then return end -- учебная плоть блин
  if not self.prev_pos then
    self.prev_pos=vector():set(0,-100,0)
  end
  if self.prev_pos:distance_to(npc:position())>20 then
    self.prev_pos=npc:position()
    local list=amk_mod.get_anomaly_list(npc,50)
    local str=""
    local first=true
    for id,o in pairs(list) do
      if first then
        str=o.name
        first=false
      else
        str=str..","..o.name
      end
    end
--    npc:remove_all_restrictions()
    npc:add_restrictions("",str)
  end
end

function generic_object_binder:extrapolate_callback()
	local cur_pt = self.object:get_current_point_index()

    if self.object:get_script ()	== false then 
       return false
    end    
    
	if patrol(self.object:patrol()):flags(cur_pt):get() == 0 then
		--printf("_bp: generic_object_binder: extrapolate_callback: cur_pt = %d: true", cur_pt)
		return true
	end
	--printf("_bp: generic_object_binder: extrapolate_callback: cur_pt = %d: false", cur_pt)
	return false
end

function generic_object_binder:waypoint_callback(obj, action_type, index)
	if self.st.active_section ~= nil then
		xr_logic.issue_event(self.object, self.st[self.st.active_scheme], "waypoint_callback", obj, action_type, index)
	end
end

function generic_object_binder:death_callback(victim, who)
	if who:id() == db.actor:id() then
		xr_statistic.addKillCount(self.object)
	end

	if self.st.mob_death then
		xr_logic.issue_event(self.object, self.st.mob_death, "death_callback", victim, who)
	end

	if self.st.active_section then
		xr_logic.issue_event(self.object, self.st[self.st.active_scheme], "death_callback", victim, who)
	end

	smart_terrain.on_death( self.object:id() )

	--' Наносим небольшой импульс вперед.
	local h = hit()
	h.draftsman = self.object
	h.type = hit.fire_wound
	h.direction = db.actor:position():sub(self.object:position())
	h:bone("pelvis")
	h.power = 1
	h.impulse = 10
	self.object:hit(h)

  local mob=self.object
  if mob:clsid()==clsid.controller_s then
    local zomb=amk.load_table("zombies")
    for k,v in pairs(zomb) do
      if v.master==mob:id() then
        if amk_mod.dezombify(k,v) then
          zomb[k]=nil
        end
      end
    end
    amk.save_table("zombies",zomb)
  end  
end

function generic_object_binder:hit_callback(obj, amount, local_direction, who, bone_index)
--	printf("HIT_CALLBACK: [%s] amount[%s]", obj:name(), amount)
	if self.st.hit then
		xr_logic.issue_event(self.object, self.st.hit, "hit_callback", obj, amount, local_direction, who, bone_index)
	end
  -- amk.mylog(obj:name().." "..local_direction.x.." "..local_direction.y.." "..local_direction.z.." "..bone_index.." "..amount.." "..who:name())
  if bone_index==14 and string.find(obj:section(),"bloodsucker") then
    local h=hit()
		h.type = hit.fire_wound
		h.power = 100*local_direction.x*local_direction.x*local_direction.x*local_direction.x
		h.impulse = h.power
    h.draftsman = who
    h.direction = vector():set(0,-1,0)
    obj:hit(h)    
  end
end

function generic_object_binder:net_spawn(sobject)
	if not object_binder.net_spawn(self, sobject) then
		return false
	end

	db.add_obj(self.object)

	xr_gulag.setup_gulag_and_logic_on_spawn( self.object, self.st, sobject, modules.stype_mobile, self.loaded )

	amk.on_net_spawn(self.object)

	return true
end

function generic_object_binder:net_destroy()
	self.object:set_callback(callback.death,				nil)
	self.object:set_callback(callback.patrol_path_in_point, nil)
	self.object:set_callback(callback.hit,					nil)

	local st = db.storage[self.object:id()]
	if st and st.active_scheme then
		xr_logic.issue_event(self.object, st[st.active_scheme], "net_destroy")
	end
	
	db.del_obj(self.object)
	db.storage[self.object:id()] = nil

	object_binder.net_destroy(self)
end 

function generic_object_binder:reload(section)
	object_binder.reload(self, section)
	--printf("generic_object_binder:reload(): self.object:name()='%s'", self.object:name())
end

function generic_object_binder:net_save_relevant()
	--printf("generic_object_binder:net_save_relevant(): self.object:name()='%s'", self.object:name())
	return true
end

function generic_object_binder:save(packet)
	printf("generic_object_binder:save(): self.object:name()='%s'", self.object:name())
	object_binder.save(self, packet)

	xr_logic.save_obj(self.object, packet)
	if self.object:clsid() == clsid.script_trader then
		trade_manager.save(self.object, packet)
	end
end

function generic_object_binder:load(reader)
	self.loaded = true

	printf("generic_object_binder:load(): self.object:name()='%s'", self.object:name())
	object_binder.load(self, reader)

	if reader:r_eof() then
		abort("SAVE FILE IS CORRUPT")
	end

	xr_logic.load_obj(self.object, reader)
	if self.object:clsid() == clsid.script_trader then
		trade_manager.load(self.object, reader)
	end
end
