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

function actor_init    (npc)
        npc:bind_object(actor_binder(npc))
end

delayed_alife_release_objects = {}
to_delayed_alife_release_objects = {}

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 = {}
----------------------------------------------------------------------------------------------------------------------
class "actor_binder" (object_binder)
----------------------------------------------------------------------------------------------------------------------
function actor_binder:__init (obj) super(obj)
        self.bCheckStart = false
        self.weather_manager = level_weathers.get_weather_manager()
        --self.actor_detector = xr_detector.actor_detector()
        self.last_level_name = nil
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:net_spawn(data)
        printf("actor net spawn")

        level.show_indicators()

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

        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
        xr_s.on_game_load()                                    --' Distemper 03.2008 --
        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()

        --'Устанавливаем ссылку на таскменеджер
        self.task_manager = task_manager.get_task_manager()

        -- Анремте это, чтобы пропустить интро на марше.
        --self.object:give_info_portion("mar_lvl_sim")
        if level.name() ~= "marsh" then
        	sim_board.get_sim_board():start_sim()
        end
		
		amk.on_game_load(obj)

        --spawn_items.main()
        self.spawn_frame = device().frame
		self.already_jumped = false
		benchmark.main()							          --' Distemper 06.2008 --

	return true
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:net_destroy()
     
	      amk.on_game_save(obj)

         xr_sound.stop_sounds_by_id(self.object:id())
		if(actor_stats.remove_from_ranking~=nil)then
                actor_stats.remove_from_ranking(self.object:id())
        end
		xr_effects.stc_stop_particle_sounds()
    get_console():execute("hud_crosshair 1")
    get_console():execute("hud_weapon 1")
--    get_console():execute("r2_dof -0.250000,1.400000,200.000000")
--        game_stats.shutdown ()
        db.del_actor(self.object)

        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
		xrs_dyn_music.stop_sound()
        object_binder.net_destroy(self)
--		xr_sound.stop_all_sounds()
        xr_s.on_actor_destroy()                                       --' Distemper 03.2008 --
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 box_name = box:name()
    treasure_manager.take_item_from_box(box, box_name, item)

    --local smart_name = string.sub(box_name, 1, string.len(box_name)-4)
	--if(sim_board.get_sim_board().smarts_by_names[smart_name]~=nil) then
	  --  game_relations.set_gulag_relation_actor(smart_name, "enemy")
	--end
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)
        amk.on_info(npc,info_id) 
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:on_trade (item, sell_bye, money)
    if sell_bye == true then
       game_stats.money_trade_update (money)
	   xr_statistic.inc_recieved_money_counter(money)
    else
       game_stats.money_trade_update (-money)
	   xr_statistic.inc_spent_money_counter(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
        amk.on_info(npc,info_id)
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:on_item_take (obj)
    level_tasks.proceed(self.object)
    printf("on_item_take [%s]", obj:name())
    if isArtefact(obj) then
                bind_anomaly_zone.artefact_ways_by_id[obj:id()] = nil
                local artefact =  obj:get_artefact()
                artefact:FollowByPath("NULL",0,vector():set(500,500,500))
                if bind_anomaly_zone.parent_zones_by_artefact_id[obj:id()] ~= nil then
                        bind_anomaly_zone.parent_zones_by_artefact_id[obj:id()]:on_artefact_take()
                end
        end
        for k,v in pairs(task_manager:get_task_manager().task_info) do
                if(v.type=="bring_item" and v.state~="finished") then
                        v:on_item_take(obj)
                end
        end
    --game_stats.update_take_item (obj, self.object)
        amk.on_item_take(obj)
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:on_item_drop (obj)
    level_tasks.proceed(self.object)
        for k,v in pairs(task_manager:get_task_manager().task_info) do
                if(v.type=="bring_item" and v.state~="finished") then
                        v:on_item_drop(obj)
                end
        end
    --game_stats.update_drop_item (obj, self.object)
	amk.on_item_drop(obj)
end
----------------------------------------------------------------------------------------------------------------------

function actor_binder:task_callback(_task, _state)
    if _state ~= task.fail then
		if _state == task.completed then
			news_manager.send_task(db.actor, "complete", _task)
		else
			news_manager.send_task(db.actor, "new", _task)
		end
	end

	task_manager.task_callback(_task, _state)
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
----------------------------------------------------------------------------------------------------------------------
local is_kill = false

function actor_binder:update(delta)
        object_binder.update(self, delta)
		
if is_kill == false then
local obj = alife():object("sim_default_stalker_217210")
  if obj then
    local name = obj:name()
    alife():release(obj, true)
    --sak.dbglog("%s killed", name)
  else
    --sak.dbglog("npc not found")
  end
  is_kill = true
end		
		
		-- $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 

        if self.already_jumped==false and jump_level.need_jump==true and (device().frame > self.spawn_frame+2000) then
			jump_level.try_to_jump()
			self.already_jumped = true
		return
	end

        -- DEBUG slowdown
--        slowdown.update()

        local time = time_global()

        game_stats.update (delta, self.object)

        -- апдейт погоды
        self.weather_manager:update()

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

        --' Апдейт саундменеджера
        xr_sound.update(self.object:id())

        --' Проверка потери жизни
--[[
        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 self.object:is_talking() then
			if self.weapon_hide_in_dialog == false then
				--printf("PL:HIDE_D1 ---> self.weapon_hide = [%s] weapon_hide = [%s]", tostring(self.weapon_hide), tostring(weapon_hide))
				self.object:hide_weapon()
				self.weapon_hide_in_dialog = true
				--printf("PL:HIDE_D2 ---> self.weapon_hide = [%s] weapon_hide = [%s]", tostring(self.weapon_hide), tostring(weapon_hide))
			end
		else
			if self.weapon_hide_in_dialog == true then
				--printf("PL:RESTORE_D1 ---> self.weapon_hide = [%s] weapon_hide = [%s]", tostring(self.weapon_hide), tostring(weapon_hide))
				self.object:restore_weapon()
				self.weapon_hide_in_dialog = false
				--printf("PL:RESTORE_D2 ---> self.weapon_hide = [%s] weapon_hide = [%s]", tostring(self.weapon_hide), tostring(weapon_hide))
			end
        end


        -- Апдейт прятание оружия игрока в зоне sr_no_weapon
        if check_for_weapon_hide_by_zones() == true then
        	--printf("weapon_hide1 = [%s]", tostring(weapon_hide))
                if self.weapon_hide == false then
                		--printf("PL:HIDE_W1 ---> self.weapon_hide = [%s] weapon_hide = [%s]", tostring(self.weapon_hide), tostring(weapon_hide))
                        self.object:hide_weapon()
                        self.weapon_hide = true
						--printf("PL:HIDE_W2 ---> self.weapon_hide = [%s] weapon_hide = [%s]", tostring(self.weapon_hide), tostring(weapon_hide))
                end
        else
        	--printf("weapon_hide3 = [%s]", tostring(weapon_hide))
                if self.weapon_hide == true then
                		--printf("PL:RESTORE_W1 ---> self.weapon_hide = [%s] weapon_hide = [%s]", tostring(self.weapon_hide), tostring(weapon_hide))
                        self.object:restore_weapon()
                        self.weapon_hide = false
						--printf("PL:RESTORE_W2 ---> self.weapon_hide = [%s] weapon_hide = [%s]", tostring(self.weapon_hide), tostring(weapon_hide))
                end
        end

        -- обновление рестрикторов, которые под логикой, срабатывает через интервалы времени
        if self.next_restrictors_update_time < time then

                self.next_restrictors_update_time = time + 200

                self.task_manager: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

    --[[local hud_demo = get_hud()

    local custom_static_demo = hud_demo:GetCustomStatic("cs_demo_play")
    if custom_static_demo == nil then
		hud_demo:AddCustomStatic("cs_demo_play", true)
		if level.name() == "agroprom_underground" then
			hud_demo:GetCustomStatic("cs_demo_play"):wnd():SetTextST("st_demo_agr")
		elseif level.name() == "military_nvidia" then
			hud_demo:GetCustomStatic("cs_demo_play"):wnd():SetTextST("st_demo_mil")
		else
			hud_demo:GetCustomStatic("cs_demo_play"):wnd():SetTextST("st_demo_play")
		end
    end

    if jump_level.need_jump==true then
		hud_demo:GetCustomStatic("cs_demo_play"):wnd():SetTextST("L: " .. level.name() .. " frame [" ..
									tostring(device().frame) ..
									"] delta[" ..
									tostring(device().frame - self.spawn_frame) ..
									"]")
	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



	 if self.bCheckStart then
			printf("SET DEFAULT INFOS")

			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

		--' Distemper 03.2008 --
	if xrs_dyn_music.play_combat == 0 then
			xrs_dyn_music.interactive_music(0)
	elseif xrs_dyn_music.play_combat == 1 then
			xrs_dyn_music.interactive_music(20)
	elseif xrs_dyn_music.play_combat == 2 then
			xrs_dyn_music.interactive_music(10)
	end

	amk.on_actor_upade(delta)
	xr_s.on_actor_update(delta)
			--' end  --
	if xr_surge_hide.start_surge then
		if not xr_surge_hide.weather_surge then
			xr_surge_hide.weather_surge = true
			level.set_weather("default_cloudy", true)
		end
		local diff_sec = math.ceil(game.get_game_time():diffSec(xr_surge_hide.initialization_time)/level.get_time_factor())
		local time_before_lag_noosphere = 0
		local time_before_give_task = 0
		if level.name() == "marsh" then
			time_before_lag_noosphere = 12
			time_before_give_task = 15
		else
			time_before_lag_noosphere = 17
			time_before_give_task = 27
		end
		if diff_sec>=time_before_lag_noosphere and xr_surge_hide.phase == 1 then
			xr_surge_hide.activate_surge()
		elseif diff_sec>=time_before_give_task and xr_surge_hide.phase == 2 then
			xr_surge_hide.activate_surge(xr_surge_hide.time_before_surge)
		end
	end

	local al = alife()
	if al ~= nil then
		local name = al:level_name(al:level_id())
		if(self.last_level_name==nil) then
			self.last_level_name = name
		else
			if(name~=self.last_level_name) then
	            self.last_level_name = name
				local time = xr_surge_hide.surge_can_be_started(name)
				if time then
                    xr_surge_hide.activate_surge(time)
	            end
			end
		end
	end
	if guiders.teleported_to_another_level and not guiders.level_changed then
		guiders.action_teleport_to_point()
	end
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:save(packet)

        set_save_marker(packet, "save", false, "actor_binder")

        object_binder.save(self, packet)

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


        --' Сохраняем данные об отключенном вводе
        if self.st.disable_input_time == nil then
                packet:w_bool(false)
        else
                packet: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)
        release_body_manager.get_release_body_manager():save(packet) --' Distemper 12.02.2008
		xr_surge_hide.save(packet)
        sr_psy_antenna.save( packet )
        --self.actor_detector:save(packet)

		packet:w_bool(sim_board.get_sim_board().simulation_started)

        -- Сохранение списка ожидания на команду атаки от игрока
        local n = 0
        for k,v in pairs(sim_combat.wait_for_combat) do
                n = n + 1
        end
        packet:w_u8(n)
        for k,v in pairs(sim_combat.wait_for_combat) do
                packet:w_u16(k)
                packet:w_stringZ(v)
        end
        xr_sound.actor_save(packet)
    	packet:w_stringZ(tostring(self.last_level_name))
		xr_statistic.save(packet)
		guiders.save(packet)
		treasure_manager.save(packet)
		n = 0
		for k,v in pairs(delayed_alife_release_objects) do
			n = n + 1
		end
		packet:w_u8(n)
		for k,v in pairs (delayed_alife_release_objects) do
			printf("TO_RELEASING OBJ:[%s]", tostring(k))
			packet:w_u16(k)
		end
		n = 0
		for k,v in pairs(db.script_ids) do
			n = n + 1
		end
		packet:w_u8(n)
		for k,v in pairs (db.script_ids) do
			packet:w_u16(k)
			packet:w_stringZ(v)
		end
        set_save_marker(packet, "save", true, "actor_binder")
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:load(reader)
        set_save_marker(reader, "load", false, "actor_binder")

        object_binder.load(self, reader)

        --' Загружаем уровень сложности
        local game_difficulty = reader:r_u8()
        printf("load game_difficulty %s", tostring(game_difficulty))
     --   if game_difficulty >= 128 then 
     --   game_difficulty = game_difficulty - 128 
     --   end
        get_console():execute("g_game_difficulty "..game_difficulty_by_num[game_difficulty])

        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)
        release_body_manager.get_release_body_manager():load(reader) --' Distemper 12.02.2008
		xr_surge_hide.load(reader)
        sr_psy_antenna.load(reader)
        --self.actor_detector:load(reader)

		sim_board.get_sim_board().simulation_started = reader:r_bool()

        -- Загрузка списка ожидания на команду атаки от игрока
        local n = reader:r_u8()
        sim_combat.wait_for_combat = {}
        for i = 1,n do
                sim_combat.wait_for_combat[reader:r_u16()] = reader:r_stringZ()
        end

        xr_sound.actor_load(reader)
        local n = reader:r_stringZ()
        if(n~="nil") then
            self.last_level_name = n
        end
		xr_statistic.load(reader)
		guiders.load(reader)
		treasure_manager.load(reader)
		n = reader:r_u8()
		for i = 1,n do
			to_delayed_alife_release_objects[reader:r_u16()] = true
		end
		printf("delayed_alife_release_objects")
		print_table(delayed_alife_release_objects)
		n = reader:r_u8()
		for i = 1,n do
			db.script_ids[reader:r_u16()] = reader:r_stringZ()
		end
        set_save_marker(reader, "load", true, "actor_binder")
end
----------------------------------------------------------------------------------------------------------------------

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

function check_for_weapon_hide_by_zones()
	for k,v in pairs(weapon_hide) do
		if v == true then
			return true
		end
	end
	return false
end
-- Weapon functions
function hide_weapon(zone_id)
	weapon_hide[zone_id] = true
end
function restore_weapon(zone_id)
	weapon_hide[zone_id] = false
end


function add_to_delayed_release(obj_id)
	printf("TO_RELEASING_add OBJ:[%s]", tostring(obj_id))
	delayed_alife_release_objects[obj_id] = true
end
function del_to_delayed_release(obj_id)
	printf("TO_RELEASING_del OBJ:[%s]", tostring(obj_id))
	delayed_alife_release_objects[obj_id] = nil
end