function init    (obj)
   xr_motivator.AddToMotivator(obj)
end

function actor_init    (npc)
   npc:bind_object(actor_binder(npc))
  -- level_tasks.add_location(707,"blue_location","Лукаш")
  -- level_tasks.add_location(702,"blue_location","Макс")
  -- level_tasks.add_location(728,"blue_location","Повар")
end

local game_difficulty_by_num = {
   [0] = "gd_novice",
   [1] = "gd_stalker",
   [2] = "gd_veteran",
   [3] = "gd_master"
   }

lasthealth  = 0
lasttime    = 0
post_process = 0
local weapon_hide = false
----------------------------------------------------------------------------------------------------------------------
class "actor_binder" (object_binder)
----------------------------------------------------------------------------------------------------------------------
function actor_binder:__init (obj) super(obj)
   self.bCheckStart = false
   self.weather_manager = level_weathers.WeatherManager()
   self.actor_detector = xr_detector.actor_detector()
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:net_spawn(data)
   printf("actor net spawn")   

   level.show_indicators()

    self.bCheckStart = true
    self.weapon_hide = false -- спрятано или нет оружие при разговоре.
    weapon_hide = false -- устанавливаем глобальный дефолтовый флаг.

    if object_binder.net_spawn(self,data) == false then
        return false
    end
    

    db.add_actor(self.object)
  
    if self.st.disable_input_time == nil then
        level.enable_input()
    end
 
    self.weather_manager:reset()
--  game_stats.initialize ()

    if(actor_stats.add_to_ranking~=nil)then
        actor_stats.add_to_ranking(self.object:id())
    end

    --' Загружаем настройки дропа
    death_manager.init_drop_settings()   

  if xrs_ai then xrs_ai.actor_net_spawn(self) end   

  if level_weathers.dynamic_weather_level(level.name()) and
	       amk.load_variable("blowout",0)==0 and
	       amk.load_variable("blowout_happened",0)==1 then
	    level.set_weather("chernobyl")
	elseif level_weathers.dynamic_weather_level(level.name()) and
	       amk.load_variable("blowout",0)==0 and
	       amk.load_variable("blowout_happened",0)==0 then
	  	level_weathers.load_weather()
	end

	-- addded for faction change mod
	faction_change.delayed_military_join()
	-- end of addition
	
  -- added by xStream for AMK miniSDK
  amk.on_game_load(obj)
  -- end of addition
  return true
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:net_destroy()

  -- added by xStream for AMK miniSDK
  amk.on_game_save(obj)
  -- end of addition

  if(actor_stats.remove_from_ranking~=nil)then
    actor_stats.remove_from_ranking(self.object:id())
  end
--  game_stats.shutdown ()
  db.del_actor(self.object)

    sr_light.clean_up ()

    self.object:set_callback(callback.inventory_info, nil)
    self.object:set_callback(callback.article_info, nil)
    self.object:set_callback(callback.on_item_take, nil)
    self.object:set_callback(callback.on_item_drop, nil)
    --self.object:set_callback(callback.actor_sleep, nil)
    self.object:set_callback(callback.task_state, nil)
    self.object:set_callback(callback.level_border_enter, nil)
    self.object:set_callback(callback.level_border_exit, nil)
    self.object:set_callback(callback.take_item_from_box, nil)

    if sr_psy_antenna.psy_antenna then
        sr_psy_antenna.psy_antenna:destroy()
        sr_psy_antenna.psy_antenna = false
    end

    xr_sound.stop_all_sound_object()

    object_binder.net_destroy(self)
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:reinit()
  object_binder.reinit(self)
  
  local npc_id = self.object:id()

  db.storage[npc_id] = { }

  self.st = db.storage[npc_id]
  self.st.pstor = nil

  self.next_restrictors_update_time = -10000

  self.object:set_callback(callback.inventory_info, self.info_callback, self)
  self.object:set_callback(callback.article_info, self.article_callback, self)
  self.object:set_callback(callback.on_item_take, self.on_item_take, self)
  self.object:set_callback(callback.on_item_drop, self.on_item_drop, self)
  self.object:set_callback(callback.trade_sell_buy_item, self.on_trade, self) -- for game stats
  --self.object:set_callback(callback.actor_sleep, self.sleep_callback, self)
  self.object:set_callback(callback.task_state, self.task_callback, self)
  --self.object:set_callback(callback.map_location_added, self.map_location_added_callback, self)
  self.object:set_callback(callback.level_border_enter, self.level_border_enter, self)
  self.object:set_callback(callback.level_border_exit, self.level_border_exit, self)
  self.object:set_callback(callback.take_item_from_box, self.take_item_from_box, self)
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:take_item_from_box(box, item)
    local story_id = box:story_id()
    if story_id == nil then
        return
    end
    treasure_manager.take_item_from_box(box, story_id)
--[[  
    local respawner = se_respawn.get_respawner_by_parent(story_id)
    if respawner == nil then
       return
    end
  
    --' Необходимо уменьшить счетчик в респавнере
    respawner:remove_spawned(item:id())

    local smart_terrain = db.strn_by_respawn[respawner:name()]
    if smart_terrain == nil then
        return
    end

    local npc = smart_terrain.gulag:get_nearest_online_obj(db.actor:position())
    if npc ~= nil then
      xr_sound.set_sound_play(npc, "reac_box")
      xr_gulag.setGulagEnemy(smart_terrain:name() , db.actor)   
    end
]]
  -- added by xStream for AMK miniSDK
  amk.on_item_take_from_box(box,item)
  -- end of addition

end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:level_border_enter(npc, info_id)
  self.actor_detector:actor_enter()
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:level_border_exit(npc, info_id)
  self.actor_detector:actor_exit()
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:info_callback(npc, info_id)
  printf("*INFO*: npc='%s' id='%s'", npc:name(), info_id)
  --' Сюжет
  level_tasks.proceed(self.object)
  -- Отметки на карте
  level_tasks.process_info_portion(info_id)
  
  -- added by xStream for AMK miniSDK
  amk.on_info(npc,info_id)
  -- end of addition
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:on_trade (item, sell_bye, money)
    if sell_bye == true then
       game_stats.money_trade_update (money)
    else       
       game_stats.money_trade_update (-money) 
    end   
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:article_callback(npc, group, name)
  --printf("article_callback [%s][%s]", group, name)
  if device().precache_frame >1 then return end
  
  if group == "Diary" then
    news_manager.send_encyclopedy("diary", group)
  else
    news_manager.send_encyclopedy("encyclopedy", group)
  end
end
----------------------------------------------------------------------------------------------------------------------
    
-- dunin ammo
	local ammo_aggregation = true
	local ps_need_update = false

function actor_binder:on_item_take (obj)
	if obj:clsid() ~= clsid.wpn_ammo then
    level_tasks.proceed(self.object)
	else --obj:clsid() == clsid.wpn_ammo
		if ammo_aggregation then
			if dunin_ammo.on_take(obj) then
				ps_need_update = true
			end
		end
	end
    if xrs_ai then xrs_ai.actor_item_take(obj) end
    --game_stats.update_take_item (obj, self.object)
-- dunin ammo end

	if rx_ai then
		rx_ai.actor_item_take(obj)
	end 

  -- added by xStream for AMK miniSDK
  amk.on_item_take(obj)
  -- end of addition
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:on_item_drop (obj)
    level_tasks.proceed(self.object)
    --game_stats.update_drop_item (obj, self.object)
    -- if level.vertex_position(db.actor:level_vertex_id()):distance_to(db.actor:position())>1 then
      -- amk.mylog("Здесь нет вертексов")
    -- else
      -- amk.mylog("Вертекс "..db.actor:level_vertex_id().." "..db.actor:game_vertex_id())
    -- end 
    
  -- added by xStream for AMK miniSDK
  amk.on_item_drop(obj)
  -- end of addition
end
----------------------------------------------------------------------------------------------------------------------

function actor_binder:task_callback(_task, _objective, _state)
  task_manager.task_callback(_task:get_id(), _objective:get_idx(), _state)
  if _objective:get_idx() == 0 then
    if _state == task.fail then
      news_manager.send_task(db.actor, "fail", _task, _objective)
    elseif _state == task.completed then
      task_manager.reward_by_task(_task)
      news_manager.send_task(db.actor, "complete", _task, _objective)
    else
      news_manager.send_task(db.actor, "new", _task, _objective)
    end
  else
    if _task:get_objective(0):get_state() == task.in_progress then
      news_manager.send_task(db.actor, "update", _task, _objective)
    end
  end
end

----------------------------------------------------------------------------------------------------------------------
function actor_binder:map_location_added_callback(spot_type_str, object_id)
  if (false==app_ready()) or (device().precache_frame>1) then return end
  --'news_manager.send_task(db.actor, "new")
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:update(delta)
	-- ATMEN MOD  ;adds heavy breathing when you sprint  ;atmen1 = heavy breathe  atmen2 = heavy breathe, heartbeat, tired message
	-- atmen.atmen1()
	-- atmen.atmen2()
	-- ATMEN MOD end
    object_binder.update(self, delta)
    -- DEBUG slowdown
    -- slowdown.update()
   local time = time_global()
  
   game_stats.update (delta, self.object)

  -- $DreamMod  апдейт схемы сна
  if sleep_manager.is_sleep_active() and xr_conditions.actor_dead() then
    xr_logic.issue_event(db.actor, db.storage[db.actor:id()]["ar_sleep"], "update")
  end

  -- апдейт погоды
  self.weather_manager:update()
  
  -- апдейт схемы детектора
  self.actor_detector:update()

  -- апдейт звуковой схемы актера
  xr_sound.update_actor()
    
 -- ----------------------------------------------------- ARENA_EXTENSION_MOD--------------------------------------------------------
	aem_manager.get_aem():update()

	--'for debug only
	--aem_grenade.scan_dif()
-- ----------------------------------------------------- ARENA_EXTENSION_MOD--------------------------------------------------------

 --' Проверка потери жизни









--[[
  if self.object.health - lasthealth > 0.001 or
     self.object.health - lasthealth < -0.001 then
    printf("%f | %f", self.object.health, self.object.health - lasthealth, game.time() - lasttime)
    lasthealth = self.object.health
    lasttime = game.time()
  end
]]  
  -- Обновление отключения ввода с клавиатуры.
  if self.st.disable_input_time ~= nil and
     game.get_game_time():diffSec(self.st.disable_input_time) >= self.st.disable_input_idle 
  then
    level.enable_input()
    self.st.disable_input_time = nil
  end
  -- Обновление сна с переносом чувака в указанную позицию
  if self.st.sleep_relocate_time ~= nil and
     game.get_game_time():diffSec(self.st.sleep_relocate_time) >= self.st.sleep_relocate_idle 
  then
    self.object:set_actor_position(self.st.sleep_relocate_point)
    local dir = self.st.sleep_relocate_point:sub(self.st.sleep_relocate_look)
    self.object:set_actor_direction(dir:getH())
    self.st.sleep_relocate_time = nil
  end

  -- Апдейт прятание оружия игрока во время диалога
  if weapon_hide == true or self.object:is_talking() then
    if self.weapon_hide == false then
      self.object:hide_weapon()
      self.weapon_hide = true
    end
  else
    if self.weapon_hide == true then
      self.object:restore_weapon()
      self.weapon_hide = false
    end
  end 
 -- обновление рестрикторов, которые под логикой, срабатывает через интервалы времени
  if self.next_restrictors_update_time < time then
    bind_restrictor.actor_update(delta)

    self.next_restrictors_update_time = time + 200
    
    --disabled the autoquests
    --task_manager.actor_update()
    --
  end

  -- обновление постпроцессов
  if post_process ~= 0 then
    if post_process:update () == true then
       post_process = 0
    end
  end

  -- обновление пси-антенны
  if sr_psy_antenna.psy_antenna then
    sr_psy_antenna.psy_antenna:update(delta)
  end

  --' Вывод сообщения о большой радиации
  if self.object.radiation >= 0.7 then
    local hud = get_hud()
    local custom_static = hud:GetCustomStatic("cs_radiation_danger")
    if custom_static == nil then
      hud:AddCustomStatic("cs_radiation_danger", true)
      hud:GetCustomStatic("cs_radiation_danger"):wnd():SetTextST("st_radiation_danger")
    end
  else
    local hud = get_hud()
    local custom_static = hud:GetCustomStatic("cs_radiation_danger")
    if custom_static ~= nil then
      hud:RemoveCustomStatic("cs_radiation_danger")
    end
  end

	-- UI Radiation Mod additions - erase "  --" from the beginning of each line to activate
  --	if (ui_rad and self.object) then
  --		ui_rad.update(self.object)
  --	end
	-- UI Radiation Mod additions

	-- dunin ammo
	if ps_need_update then
		ps_need_update = false
		if ammo_aggregation and not self.object:is_talking() then
			dunin_ammo.on_update()
		end
	end

	-- dunin ammo end
	
  if self.bCheckStart then
    printf("SET DEFAULT INFOS")   

    if not has_alife_info("storyline_actor_start") and
       (level.name() == "l01_escape")
    then
      self.object:give_info_portion("storyline_actor_start")
      _G.g_start_avi = true
      printf("*AVI* RUN START AVI")     
    end

--    if not has_alife_info("encyclopedy") then
--      self.object:give_info_portion("encyclopedy")
--    end

    if not has_alife_info("global_dialogs") then
      self.object:give_info_portion("global_dialogs")
    end

    if not has_alife_info("level_changer_icons") then
      self.object:give_info_portion("level_changer_icons")
    end

    level_tasks.add_lchanger_location()

    self.bCheckStart = false    
  end
     
	if rx_ai then rx_ai.actor_update() end
	 
	-- mod: function calls for automatic antirad injection
	if auto_injection.system_enabled() then
		auto_injection.check_auto_injection_suit()
		auto_injection.check_antirad_supplies()
		auto_injection.check_radiation()
	end
	-- mod: function calls for automatic antirad injection - end
	
	oblivion_lost.on_actor_update()
	
  -- added by xStream for AMK miniSDK
  amk.on_actor_upade(delta)
  -- end of addition
  -- added by Red75. Контроль за переполнением 
  if self.warning then
    self.warning=nil
    get_hud():AddCustomStatic("hud_save_warning")
    local wnd=get_hud():GetCustomStatic("hud_save_warning"):wnd()
    if self.critical==1 then
      wnd:SetTextST("WARNING!!! Buffer overrun error! Transmutation data didn't saved! Wait until previous transmutations ends and try to save again.")
      self.critical=nil
    elseif self.critical==2 then
      wnd:SetTextST("WARNING!!! Buffer overrun error! New transmutation is broken. It's recommended to load the last save.")
      self.critical=nil
    else
      wnd:SetTextST("Warning! Amount of saved data soon will exceed the limit! Pass all the given tasks. Wait until all transmutations completed. Do not start new tasks. Do not begin new transmutations.")
    end
  elseif self.wt and self.wt<time_global() then
    self.wt=nil
    if get_hud():GetCustomStatic("hud_save_warning") then
      get_hud():RemoveCustomStatic("hud_save_warning")
    end
  end
if xrs_ai then xrs_ai.actor_update(delta) end
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:save(packet)
  local pk1=fake_net_packet.fake_net_packet()
  self:save_old(pk1)
  amk.mylog("Packet size is "..pk1:w_tell())
  if pk1:w_tell()>7500 then
    self.warning=true
    self.critical=1
    self.wt=time_global()+60000
    amk.emergency_cleanup()
    self:save_old(packet)
    amk.mylog("Actor packet size is "..packet:w_tell().."!")
    amk.emergency_restore()
  elseif pk1:w_tell()>6000 then
    self.warning=true
    self.wt=time_global()+60000
    self:save_old(packet)
  else
    self:save_old(packet)
    self.wt=time_global()
  end
end


function actor_binder:save_old(packet)
	if rx_ai then rx_ai.actor_save(packet) end
	local save_treasure_manager = true
	
	printf("actor_binder:save(): self.object:name()='%s'", self.object:name())
	object_binder.save(self, packet)

	--' Сохраняем уровень сложности
	if save_treasure_manager == true then
		packet:w_u8(level.get_game_difficulty() + 128)
	else
		packet:w_u8(level.get_game_difficulty())
	end


	--' Сохраняем данные об отключенном вводе
	if self.st.disable_input_time == nil then
		packet:w_bool(false)
	else
		packer:w_bool(true)
		utils.w_CTime(packet, self.st.disable_input_time)
	end

	xr_logic.pstor_save_all(self.object, packet)
	self.weather_manager:save(packet)

	sr_psy_antenna.save( packet )
	
	if save_treasure_manager == true then
		treasure_manager.save(packet)      
	end                                  

	task_manager.save(packet)
	self.actor_detector:save(packet)	
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:load(reader)
	printf("actor_binder:load(): self.object:name()='%s'", self.object:name())
	object_binder.load(self, reader)
	printf("actor_binder:object_binder.load(): self.object:name()='%s'", self.object:name())

	--' Загружаем уровень сложности
	local game_difficulty = reader:r_u8()
	
	local load_treasure_manager = false      
	if game_difficulty >= 128 then           
		game_difficulty = game_difficulty - 128
		load_treasure_manager = true           
	end                                      

	
	get_console():execute("g_game_difficulty "..game_difficulty_by_num[game_difficulty])

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

	local stored_input_time = reader:r_u8()
	if stored_input_time == true then
		self.st.disable_input_time = utils.r_CTime(reader)
	end

	xr_logic.pstor_load_all(self.object, reader)
	self.weather_manager:load(reader)

	sr_psy_antenna.load(reader)
	
	if load_treasure_manager == true then
		treasure_manager.load(reader)      
	end                                  

	
	task_manager.load(reader)
	self.actor_detector:load(reader)
  
  if xr_logic.pstor_retrieve(self.object,"emerg",false) then -- нельзя использовать amk.load_varible(), так как db.actor ещё не определён
    self.warning=true
    self.critical=2
    self.wt=time_global()+60000
  end
end
----------------------------------------------------------------------------------------------------------------------

--старт префетча звуков
--if string.find(command_line(), "-noprefetch") == nil then
--  sound_prefetch.prefetch_sounds()
--end


-- Weapon functions
function hide_weapon()
  weapon_hide = true
end
function restore_weapon()
  weapon_hide = false
end

// this is test for section iteration
/**
local function test_section_iteration(file_name, section_name)
  printf      ("file    : %s",file_name)
  printf      ("section : %s",section_name)
  
  local     file = ini_file(file_name)
  local     n = file:line_count(section_name)
  printf      ("lines   : %d",n)
  
  local     id, value = "", "", result
  for i=0,n-1 do
    result, id, value = file:r_line(section_name,i,"","")
    printf    ("line %d : %s = %s",i,id,value)
  end
end

test_section_iteration("system.ltx","space_restrictor")
/**/


