----------------------------------------------------------------------------------------------------------------------
--	Схема лагерь. Чудак(и) у костра.
--	автор: Диденко Руслан (Stohe)
--	TODO: 
----------------------------------------------------------------------------------------------------------------------
--function printf()
--end

kamps = {}
kamp_stalkers = {} -- могут ли сталкеры в лагере юзаться игроком.
-- Объявления итераторов
local k,v,kk,vv = 0,0,0,0
---------------------------------------------------------------------------------------------------------------------
--Evaluators
----------------------------------------------------------------------------------------------------------------------
--' Условие завершения скрипта
class "evaluator_kamp_end" (property_evaluator)
function evaluator_kamp_end:__init(name, storage) super (nil, name)
	self.a = storage
end
function evaluator_kamp_end:evaluate()
	return not xr_logic.is_active(self.object, self.a)
end
--' Находимся ли мы на заданной позиции
class "evaluator_on_position" (property_evaluator)
function evaluator_on_position:__init(name, storage) super (nil, name)
	self.a = storage
end
function evaluator_on_position:evaluate()
    if self.object:level_vertex_id() == self.a.pos_vertex then
		return true
	end
	return false
end
----------------------------------------------------------------------------------------------------------------------
--Actions
----------------------------------------------------------------------------------------------------------------------
--' Идет в заданную область
class "action_go_position" (action_base)
function action_go_position:__init (npc_name,action_name,storage) super (nil,action_name)
	self.a = storage
end
function action_go_position:initialize()
	action_base.initialize(self)
--	self.object:set_node_evaluator()
--	self.object:set_path_evaluator()
	self.object:set_desired_position()
	self.object:set_desired_direction()
	
	self.a.pos_vertex = nil
end
function action_go_position:execute ()
	action_base.execute (self)

	if db.actor then
		if xr_logic.try_switch_to_another_section(self.object, self.a, db.actor) then
			return
		end
	end	
	
	local tmp_pos_vertex = kamps[self.a.center_point]:getDestVertex(self.object:id(), self.a.radius)
	if self.a.pos_vertex ~= tmp_pos_vertex then
		self.a.pos_vertex = tmp_pos_vertex
		
		if not self.object:accessible(self.a.pos_vertex) then
			--'printf("[%s] KAMP NODE NOT ACCESSIBLE. Get accessible nearest", self.object:name())
			local ttp = vector():set(0,0,0)
			self.a.pos_vertex = self.object:accessible_nearest(level.vertex_position(self.a.pos_vertex), ttp)
		end
		
		self.a.pp = patrol(self.a.center_point):level_vertex_id(0)
		self.a.pp = level.vertex_in_direction(self.a.pp, vector():set(math.random(-1,1), 0, math.random(-1,1)), math.random(0,0.5))
		self.object:set_dest_level_vertex_id(self.a.pos_vertex)
		self.object:set_desired_direction(vector():sub(level.vertex_position(self.a.pp),level.vertex_position(self.a.pos_vertex)))
		self.object:set_path_type(game_object.level_path)
		state_mgr.set_state(self.object, self.a.def_state_moving)
	end
end
function action_go_position:finalize ()
	action_base.finalize (self)
end

--' Просто сидит и втыкает
class "action_wait" (action_base)
function action_wait:__init (npc_name,action_name,storage) super (nil,action_name)
	self.a = storage
end
function action_wait:initialize()
	action_base.initialize(self)
--	self.object:set_node_evaluator()
--	self.object:set_path_evaluator()
	self.object:set_desired_position()
	self.object:set_desired_direction()
	
	kamps[self.a.center_point]:increasePops(self.object)
end
function action_wait:activate_scheme()
end
function action_wait:execute()
	action_base.execute (self)
	if db.actor then
		if xr_logic.try_switch_to_another_section(self.object, self.a, db.actor) then
			return
		end
	end
	local state, sound, substate = kamps[self.a.center_point]:updateNpc(self.object)
	
	--' повернуть его лицом к центру	
	state_mgr.set_state(self.object, state, nil, nil, {look_position = level.vertex_position(self.a.pp)}, nil, nil, {subanim = substate})
	xr_sound.set_sound(self.object, sound)
end
function action_wait:finalize()
	kamps[self.a.center_point]:decreasePops(self.object)
	action_base.finalize (self)
end
function action_wait:deactivate(npc)
	kamps[self.a.center_point]:removeNpc(npc)
end
function action_wait:death_callback(npc)
	kamps[self.a.center_point]:removeNpc(npc)
end
function action_wait:net_destroy(npc)
	kamps[self.a.center_point]:removeNpc(npc)
end


class "CKampManager"
function CKampManager:__init(path)
	self.kamp_name = path
	self.patrol = patrol(path)
	self.center = self.patrol:level_vertex_id(0)
	self.position = {{dir = vector():set(1, 0, 0),	used = nil},
					 {dir = vector():set(1, 0, 1),	used = nil},
					 {dir = vector():set(0, 0, 1),	used = nil},
					 {dir = vector():set(-1, 0, 1),	used = nil},
					 {dir = vector():set(-1, 0, 0),	used = nil},
					 {dir = vector():set(-1, 0, -1),used = nil},
					 {dir = vector():set(0, 0, -1),	used = nil},
					 {dir = vector():set(1, 0, -1),	used = nil}}
	self.npc = {}
	self.population = 0
	self.kamp_state = "idle"	
	-- Где то здесь распарсим патрульный путь и проапдейтим вектор позиций.
	-- 0 вершина - центр лагеря.
	-- 1 флаг - сектор занят, в поинте можно сидеть.
	-- 2 флаг - сектор занят, в поинте нельзя сидеть.
	for k = 1, self.patrol:count() - 1 do
		-- если есть 1 или 2 флажок - отметить сектор как занятый
		if self.patrol:flag(k,1) or
		   self.patrol:flag(k,2)
		then
			-- отметить сектор как занятый
			for key,value in pairs(self.position) do
				dir = vector():sub(level.vertex_position(self.patrol:level_vertex_id(k)), level.vertex_position(self.center))
				if value.dir then
					yaw = yaw_degree(dir, value.dir)
					if yaw <=23 then
						--'printf("KAMP node[%s], sector[%s,] yaw[%s]", k, key, yaw_degree(dir, value.dir))
						value.used = -1
						break						
					end
				end
			end
			
		end
		
		-- если есть 1 флажок - создать место для сидения в точке пути
		if self.patrol:flag(k,1) then
			-- создать точку для сидения
			table.insert(self.position, {vertex = self.patrol:level_vertex_id(k)})
		end		
	end
	--print_table(self.position)
	--Таблица соответствий состояния лагеря и допустимых анимаций и звуков.	
	self.avail_state = {idle				= { directed	= { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
						pre_harmonica		= { directed	= { "wait_harmonica"},
												undirected	= { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
						harmonica			= { directed	= { "play_harmonica"},
												undirected	= { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
						post_harmonica		= { directed	= { "wait_harmonica"},
												undirected	= { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
						pre_guitar			= { directed	= { "wait_guitar"},
												undirected	= { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
						guitar				= { directed	= { "play_guitar"},
												undirected	= { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
						post_guitar			= { directed	= { "wait_guitar"},
												undirected	= { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
						story				= { directed	= { "declarate"},
												undirected	= { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
						post_story			= { directed	= { "declarate"},
												undirected	= { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
						pre_joke			= { directed	= { "declarate"},
												undirected	= { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
						joke				= { directed	= { "declarate"},
												undirected	= { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
						post_joke			= { directed	= { "declarate"},
												undirected	= { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}}}
	self.avail_sound = {idle				= { directed = "idle"},
						pre_harmonica		= { directed = "pre_harmonica", undirected = ""},
						harmonica			= { directed = "play_harmonica", undirected = ""},
						post_harmonica		= { directed = "", undirected = "reac_harmonica"},
						pre_guitar			= { directed = "pre_guitar", undirected = ""},
						guitar				= { directed = "play_guitar", undirected = ""},
						post_guitar			= { directed = "", undirected = "reac_guitar"},
						story				= { directed = "play_story", undirected = ""},
						post_story			= { directed = "", undirected = "reac_story"},
						pre_joke			= { directed = "pre_joke", undirected = ""},
						joke				= { directed = "play_joke", undirected = ""},
						post_joke			= { directed = "", undirected = "reac_joke"}}
	-- Таблица таймаутов по состоянию. Если состояние установилось, то некоторое время оно не может быт изменено.						
	self.timeout	 = {idle				= { min = 30000 },
						pre_harmonica		= { min = 3000 },
						harmonica			= { min = 5000, soundstart = true },
						post_harmonica		= { min = 3000 },
						pre_guitar			= { min = 3000 },
						guitar				= { min = 5000, soundstart = true },
						post_guitar			= { min = 3000 },
						story				= { min = 1000, soundstart = true },
						post_story			= { min = 3000 },
						pre_joke			= { min = 3000 },
						joke				= { min = 5000, soundstart = true },
						post_joke			= { min = 3000 }}
	-- Таблица глобальных состояний лагеря.
	self.kamp_states = { idle = true, 
						 pre_harmonica = false, harmonica = false, post_harmonica = false,
						 pre_guitar = false, guitar = false, post_guitar = false,
						 story = false, post_story = false,
						 pre_joke = true, joke = true, post_joke = true}
	-- Таблица допустимых переходов между состояниями с вероятностями.
	self.trans_kamp = { idle			= { idle = 0, pre_harmonica = 30, pre_guitar = 30, story = 0, pre_joke = 40 }, 
						pre_harmonica	= { harmonica = 100 }, 
						harmonica		= { post_harmonica = 100 }, 
						post_harmonica	= { idle = 70, harmonica = 30 },
						pre_guitar		= { guitar = 100 }, 
						guitar			= { post_guitar = 100 }, 
						post_guitar		= { idle = 70, guitar = 30 },
						story			= { post_story = 100 }, 
						post_story		= { idle = 100 },
						pre_joke		= { joke = 100 }, 
						joke			= { post_joke = 100 }, 
						post_joke		= { idle = 100 }}
	-- Хранилище для режиссера лагеря. Режиссерем является сталкер, затеявший необычное поведение
	self.director = nil
end
function CKampManager:selectPosition(npc_id)
	-- создаем список доступных позиций
	--printf("KAMP. [%s] called select position", npc_id)
	local free = {}
	for k,v in pairs(self.position) do
		if v.used == nil then
			table.insert(free, k)
		end
	end
	--' затем из доступных позиций выбрать рандомно одну.
	if table.getn(free) > 0 then
		--printf("KAMP [%s] free node > 0", npc_id)
		local rr = math.random(table.getn(free))
		self.position[free[rr]].used = npc_id
		self.npc[npc_id].position = free[rr]
	end
	--printf("KAMP [%s] npc table", npc_id)
	--print_table(self.npc)
	--printf("KAMP [%s] position table", npc_id)
	--print_table(self.position)
end
function CKampManager:getDestVertex(npc_id, radius)
	--printf("get dest Vertex called [%s]", npc_id)
	if self.npc[npc_id].position == nil then
		printf("-------debug_info-------------")
		print_table(self.npc)
		printf("-------debug_info-------------")
		print_table(self.position)
		printf("-------debug_info-------------")
		abort("get dest Vertex: nil [%s]", npc_id)
		return nil
	end
	
	local position = self.position[self.npc[npc_id].position]
	if position.vertex ~= nil then
		--printf("vertex preselected [%s]", npc_id)
		return position.vertex
	end
	-- высчитываем вертех по направлению
   	local pp = level.vertex_in_direction(self.center, self.position[self.npc[npc_id].position].dir, radius)
   	pp = level.vertex_in_direction(pp, vector():set(math.random(-1,1), 0, math.random(-1,1)), math.random(0,0.5))
	--printf("vertex selected [%s]", npc_id)   	
	return pp		
end
function CKampManager:proceedState(npc)
	-- Проверка на таймаут
	local npc_id = npc:id()
	local active_sound_count = npc:active_sound_count()
	if self.npc[npc_id].need_sound_begin == true then
		if active_sound_count == 0 then
			return
		else			
			self.npc[npc_id].need_sound_begin = false
		end
	end
	if self.begin ~= nil and
	   time_global() - self.begin < self.timeout[self.kamp_state].min
	then
		return
	end

	-- Если режиссер не закончил говорить - ждем конца фразы.
	if active_sound_count > 0 then
		return
	end

	--printf("Proceed state for [%s]", npc_id)
	-- В случае с историей переход обрабатывается отдельно
	if self.kamp_state == "post_story" then
		if self.story_last < self.story_max - 1 then
			self.npc[npc_id].begin = nil
			self.npc[npc_id].need_sound_begin = true
			self.director = npc_id
			self.kamp_state = "story"
			self.begin = time_global()
			for kk,vv in pairs(self.npc) do
				vv.new = true
			end		
			return
		else
			self.selected_story = nil
		end
	end
	-- Определяются допустимые в данный момент переходы.
	local temp = {}
	local max_rnd = 0
	for k,v in pairs(self.trans_kamp[self.kamp_state]) do		
		-- Определяются допустимые состояния для лагеря.
		if self.kamp_states[k] == true then
			temp[k] = v
			max_rnd = max_rnd + v
		end
	end
	-- Осуществляется рандомный взвешенный переход.
	if max_rnd == 0 then
		-- Если переходить некуда - переходим в айдл
		temp["idle"] = 100
		max_rnd = 100
	end
	local p = math.random(0,max_rnd)
	for k,v in pairs(temp) do
		p = p - v
		if p <= 0 then
			printf("Selected [%s]", k)
			if k == "idle" then
				self.director = nil
				if self.kamp_state ~= "idle" then
					self.npc[npc_id].begin = nil
				end
			else
				self.npc[npc_id].begin = nil
				if self.timeout[k].soundstart == true then
					self.npc[npc_id].need_sound_begin = true
				end
				self.director = npc_id
				self.censor = nil
			end			
			self.kamp_state = k
			self.begin = time_global()
			-- Меняем таймаут для истории
			if k == "post_story" then
				local dep = sound_theme.theme[self.selected_story].depence[self.story_last]
				if dep and dep.min and dep.max then
					self.timeout["post_story"].min = math.random(dep.min, dep.max)*1000
				end
			end
			for kk,vv in pairs(self.npc) do
				vv.new = true
			end
			return
		end
	end
end
function CKampManager:proceedRole(npc, director)
	--printf("Proceed Role for [%s]", npc:id())
	-- Определить список доступных анимаций по состоянию лагеря.
	-- определить список доступных анимаций по наличию предметов
	-- выбрать одну из них (то же самое со звуком).
	local states = 0
	local sound = ""
	local state = ""
	local npc_id = npc:id()
	if self.npc[npc_id].begin == nil or
	   time_global() - self.npc[npc_id].begin >= self.npc[npc_id].state_idle
	then
		if director then
			states = self.avail_state[self.kamp_state].directed
			sound = self.avail_sound[self.kamp_state].directed
		else
			states = self.avail_state[self.kamp_state].undirected
			sound = self.avail_sound[self.kamp_state].undirected
		end
		-- Выбирать новое состояние только раз в какое то время.
		local temp = {}
		for k,v in pairs(states) do
			if self.npc[npc_id].states[v] == true then
				table.insert(temp, v)
			end
		end
		
		-- Если мы решили говорить историю, надо выбрать какую именно говорить.
		if sound == "play_story" and self.selected_story == nil and db.story_by_id[npc_id] ~= nil then
			local story_num = table.getn(db.story_by_id[npc_id])
			if story_num > 0 then
				self.selected_story = db.story_by_id[npc_id][math.random(story_num)]
			end			
		end

		self.npc[npc_id].begin = time_global()
		state = temp[math.random(table.getn(temp))]
		self.npc[npc_id].state_selected = state
		self.npc[npc_id].state_idle = math.random(15000,20000)		
	else
		if director then
			sound = self.avail_sound[self.kamp_state].directed
		else
			sound = self.avail_sound[self.kamp_state].undirected
		end
		state = self.npc[npc_id].state_selected	
	end
	--printf("Proceed Role state [%s] sound [%s]", state, sound)	
	return state, sound
end
function CKampManager:updateNpc(npc)
	-- Проверка что сталкер может делать, а что нет.
	self:checkNpcAbility(npc)
	-- Просим лагерь выбрать текущее состояние. Менять состояние лагеря
	-- имеет право только режиссер.
	local npc_id = npc:id()
	local director = self.director == nil or self.director == npc_id
	if director	then
		self:proceedState(npc)
	end
	-- Говорим чудаку выбрать себе состояние для текущего состояния лагеря.
	local state, sound = self:proceedRole(npc, director)
	
	local substate = nil
	if state == "wait_harmonica" then
		if sound == "pre_harmonica" and self.npc[npc_id].new == true then
			xr_sound.set_sound_play(npc, "intro_music", math.random(2000,3000))
			self.npc[npc_id].new = false
		end
		state = "harmonica"
		xr_kamp.kamp_stalkers[npc_id] = false
	elseif state == "play_harmonica" then
		state = "harmonica"
		substate = 1
		xr_kamp.kamp_stalkers[npc_id] = false
	elseif state == "wait_guitar" then
		if sound == "pre_guitar" and self.npc[npc_id].new == true then
			xr_sound.set_sound_play(npc, "intro_music", math.random(2000,3000))
			self.npc[npc_id].new = false
		end
		state = "guitar"
		xr_kamp.kamp_stalkers[npc_id] = false
	elseif state == "play_guitar" then
		state = "guitar"
		substate = 1
		xr_kamp.kamp_stalkers[npc_id] = false
	elseif state == "declarate" then
		if self.npc[npc_id].new == true then
			if sound == "pre_joke" then
				xr_sound.set_sound_play(npc, "intro_joke", math.random(2000,3000))
			elseif sound == "play_joke" then
				xr_sound.set_sound_play(npc, "joke", math.random(2000,3000))
			elseif sound == "play_story" then
				xr_sound.set_sound_play(npc, self.selected_story)
				self.story_last, self.story_max = xr_sound.get_last_IDS(npc, self.selected_story)
			end
			self.npc[npc_id].new = false
		end

		if npc:character_community() == "monolith" then
			local t = math.mod(npc_id, 2)
			if t == 0 then
				state = "trans_0"
			else
				state = "trans_1"
			end
		elseif npc:character_community() == "zombied" then
			state = "trans_zombied"
		else
			local t = math.mod(npc_id, 3)
			if t == 0 then
				state = "sit"
			elseif t == 1 then
				state = "sit_ass"
			else
				state = "sit_knee"
			end
		end
		xr_kamp.kamp_stalkers[npc_id] = false
	elseif state == "trans" then
		if npc:character_community() == "monolith" then
			local t = math.mod(npc_id, 2)
			if t == 0 then
				state = "trans_0"
			else
				state = "trans_1"
			end
		elseif npc:character_community() == "zombied" then
			state = "trans_zombied"
		end
		xr_kamp.kamp_stalkers[npc_id] = false
	else
		xr_kamp.kamp_stalkers[npc_id] = true
	end
	-- Выбор реальных звуков
	if sound == "idle" then
		sound = "weather, state"
	elseif sound == "reac_guitar" then
		sound = "reac_music"
	elseif sound == "reac_harmonica" then
		sound = "reac_music"
	elseif sound == "reac_joke" then
		sound = ""	
		if self.npc[npc_id].new == true then
			if self.censor == nil then
				xr_sound.set_sound_play(npc, "reac_joke", math.random(2000,3000))
				self.censor = npc_id
			else
				xr_sound.set_sound_play(npc, "story_reac_laughter", math.random(100,300))
			end
			self.npc[npc_id].new = false
		end
	elseif sound == "reac_story" then
		sound = ""
		if self.npc[npc_id].new == true then
			local dep = sound_theme.theme[self.selected_story].depence[self.story_last+1]
			if dep then
				if dep.type == "all" then
					xr_sound.set_sound_play(npc, dep.theme, math.random(100,300))
				else
					sound = dep.theme
				end
			end
		end
	elseif sound == "reac_story" then
		sound = ""
	else
		sound = ""
	end

	--printf("Proceed Update Npc [%s] sound [%s]", state, sound)	
	return state, sound, substate
end
function CKampManager:checkNpcAbility(npc)
	local npc_id = npc:id()
	
	if npc:character_community() ~= "monolith" and
	   npc:character_community() ~= "zombied"
	then
		-- есть колбасу
		if npc:object("kolbasa") then
			self.npc[npc_id].states["eat_kolbasa"] = true
		else
			self.npc[npc_id].states["eat_kolbasa"] = false
		end
		-- пить водку
		if npc:object("vodka") then
			self.npc[npc_id].states["eat_vodka"] = true
		else
			self.npc[npc_id].states["eat_vodka"] = false
		end
		-- пить енергитический напиток
		if npc:object("energy_drink") then
			self.npc[npc_id].states["eat_energy"] = true
		else
			self.npc[npc_id].states["eat_energy"] = false
		end
		-- есть хлеб
		if npc:object("bread") then
			self.npc[npc_id].states["eat_bread"] = true
		else
			self.npc[npc_id].states["eat_bread"] = false
		end
		-- играть на гармошке
		if npc:object("harmonica_a") then
			self.npc[npc_id].states["play_harmonica"] = true
			self.npc[npc_id].states["wait_harmonica"] = true
			self.kamp_states["pre_harmonica"] = true
			self.kamp_states["harmonica"] = true
			self.kamp_states["post_harmonica"] = true
		else
			self.npc[npc_id].states["play_harmonica"] = false
			self.npc[npc_id].states["wait_harmonica"] = false
			self.kamp_states["pre_harmonica"] = false
			self.kamp_states["harmonica"] = false
			self.kamp_states["post_harmonica"] = false
		end
		-- играть на гитаре
		if npc:object("guitar_a") then
			self.npc[npc_id].states["play_guitar"] = true
			self.npc[npc_id].states["wait_guitar"] = true
			self.kamp_states["pre_guitar"] = true
			self.kamp_states["guitar"] = true
			self.kamp_states["post_guitar"] = true
		else
			self.npc[npc_id].states["play_guitar"] = false
			self.npc[npc_id].states["wait_guitar"] = false
			self.kamp_states["pre_guitar"] = false
			self.kamp_states["guitar"] = false
			self.kamp_states["post_guitar"] = false
		end
		-- анекдоты
		if self.population > 1 then
			self.kamp_states["pre_joke"] = true
			self.kamp_states["joke"] = true
			self.kamp_states["post_joke"] = true
		else
			self.kamp_states["pre_joke"] = false
			self.kamp_states["joke"] = false
			self.kamp_states["post_joke"] = false
		end	
	end
	
	-- Если чувак знает истории, надо добавить их к лагерю
--[[
	if self.population > 1 and db.story_by_id[npc:id()] ~= nil then
		self.kamp_states["story"] = true
		self.kamp_states["post_story"] = true
	else
		self.kamp_states["story"] = false
		self.kamp_states["post_story"] = false	
	end
]]
end
function CKampManager:addNpc(npc)
	printf("KAMP [%s] add npc", npc:name())
	if self.npc[npc:id()] ~= nil then
		printf("NPC is already exist")
		return
	end
	
	if npc:character_community() == "monolith" or
	   npc:character_community() == "zombied"
	then
		self.npc[npc:id()] = {name = npc:name(), position = nil, current = nil, speak = 0, states = {
								stand_wait = false, sit = false, sit_ass = false, sit_knee = false, declarate = true,
								eat_kolbasa = false, eat_vodka = false, eat_energy = false, eat_bread = false, trans = true,
								play_harmonica = false, play_guitar = false, play_joke = false, play_story = false}}
	else
		self.npc[npc:id()] = {name = npc:name(), position = nil, current = nil, speak = 0, states = {
								stand_wait = true, sit = true, sit_ass = true, sit_knee = true, declarate = true,
								eat_kolbasa = false, eat_vodka = false, eat_energy = false, eat_bread = false, trans = false,
								play_harmonica = false, play_guitar = false, play_joke = false, play_story = false}}
	end
	self:selectPosition(npc:id())	
end
function CKampManager:removeNpc(npc)
	printf("KAMP [%s] remove npc", npc:name())
	local npc_id = npc:id()
	if self.npc[npc_id] ~= nil then
		-- Если удаляем режиссера - необходимо форсированно перевести лагерь в идловое состояние.
		if self.director == npc_id then
			self.director = nil
			self.npc[npc_id].begin = nil
			self.censor = nil
			self.kamp_state = "idle"
			self.begin = time_global()
			for kk,vv in pairs(self.npc) do
				vv.new = true
			end
			xr_sound.set_sound(npc, nil)
			stop_play_sound(npc)
		end
	
		self.position[self.npc[npc_id].position].used = nil
		self.npc[npc_id] = nil
	end
end
function CKampManager:increasePops(npc)
	self.population = self.population + 1
end
function CKampManager:decreasePops(npc)
	self.population = self.population - 1
end
----------------------------------------------------------------------------------------------------------------------
--Kamp binder
----------------------------------------------------------------------------------------------------------------------
function add_to_binder(object, ini, scheme, section, storage)
	local operators		= {}
	local properties	= {}

	local manager = object:motivation_action_manager()
	
	properties["kamp_end"]		= xr_evaluators_id.stohe_kamp_base + 1
	properties["on_position"]	= xr_evaluators_id.stohe_kamp_base + 2
	properties["contact"]		= xr_evaluators_id.stohe_meet_base + 1    

	operators["go_position"]	= xr_actions_id.stohe_kamp_base + 1
	operators["wait"]		= xr_actions_id.stohe_kamp_base + 3

	-- Evaluators                                                                            
	manager:add_evaluator (properties["kamp_end"], 		this.evaluator_kamp_end		("kamp_end", storage, "kamp_end"))
	manager:add_evaluator (properties["on_position"],	this.evaluator_on_position	("kamp_on_position", storage, "kamp_on_position"))

	printf("PRP %s", stalker_ids.property_script)

	-- Actions
	local action = this.action_wait (object:name(),"action_kamp_wait", storage)
	action:add_precondition		(world_property(stalker_ids.property_alive, true))
	action:add_precondition		(world_property(stalker_ids.property_danger,false))
	action:add_precondition		(world_property(stalker_ids.property_enemy,	false))
	action:add_precondition		(world_property(stalker_ids.property_anomaly,false))
	xr_motivator.addCommonPrecondition(action)
	action:add_precondition		(world_property(properties["on_position"], 	true))
	action:add_effect 		(world_property(properties["kamp_end"], 	true))
	manager:add_action (operators["wait"], action)
	xr_logic.subscribe_action_for_events(object, storage, action)
	
	action = this.action_go_position (object:name(),"action_go_kamp", storage)
	action:add_precondition		(world_property(stalker_ids.property_alive, true))
	action:add_precondition		(world_property(stalker_ids.property_danger,false))
	action:add_precondition		(world_property(stalker_ids.property_enemy,	false))
	action:add_precondition		(world_property(stalker_ids.property_anomaly,false))
	xr_motivator.addCommonPrecondition(action)
	action:add_precondition 	(world_property(properties["on_position"], 	false))
	action:add_effect 		(world_property(properties["on_position"], 	true))
	manager:add_action (operators["go_position"], action)

	action = manager:action (xr_actions_id.alife)	
	action:add_precondition		(world_property(properties["kamp_end"],		true))

end
-- включение лагеря
function set_scheme(npc, ini, scheme, section, gulag_name)
	local st = xr_logic.assign_storage_and_bind(npc, ini, scheme, section)

	st.logic     = xr_logic.cfg_get_switch_conditions(ini, section, npc)		
    
	st.center_point = utils.cfg_get_string(ini, section, "center_point", npc, true,  gulag_name)
	st.radius		= utils.cfg_get_number(ini, section, "radius", npc, false, 2)
	
	if kamps[st.center_point] == nil then
		kamps[st.center_point] = CKampManager(st.center_point)
	end
	kamps[st.center_point]:addNpc(npc)
	st.pos_vertex = nil

	st.def_state_moving = utils.cfg_get_string(ini, section, "def_state_moving", npc, false, "", "walk")
end