diff --git a/build/gamesource/shaders/ppe/ppe_lens_flare2.ps b/build/gamesource/shaders/ppe/ppe_lens_flare2.ps
index 8790fa88534cd218c1fd91329fc95567ce76a538..2fb0e3d95105fd991b1542eb2a4f136341e884d4 100644
--- a/build/gamesource/shaders/ppe/ppe_lens_flare2.ps
+++ b/build/gamesource/shaders/ppe/ppe_lens_flare2.ps
@@ -43,5 +43,5 @@ half4 main(vs_out_pp IN):COLOR0
 		}
 
 	result /= half(NumSamples)*(LensFlareParam.z);
-	return half4(result+0.1,0.0);
+	return half4(result,0.0);
 }
\ No newline at end of file
diff --git a/build/sysconfig.cfg b/build/sysconfig.cfg
index 595abcb14e782db5c72c44363f5e0911ff0a0386..7c73de96303ea8078e8845e7816643e846e7358b 100644
--- a/build/sysconfig.cfg
+++ b/build/sysconfig.cfg
@@ -46,7 +46,7 @@ grass_frec 100
 green_lod0 50
 green_lod1 100
 green_less 20
-p_far 400
+r_far 400
 
 r_s_filter 2
 r_s_max_anisotropy 16
diff --git a/proj/SkyXEngine/vs2013/SkyXEngine.vcxproj b/proj/SkyXEngine/vs2013/SkyXEngine.vcxproj
index ef9a54c1b3c7fc98c7dc10a596d1cdd865315ac0..58cd47a2476af37d1889f9cd03b976d6a8b9969b 100644
--- a/proj/SkyXEngine/vs2013/SkyXEngine.vcxproj
+++ b/proj/SkyXEngine/vs2013/SkyXEngine.vcxproj
@@ -95,11 +95,13 @@
   </ItemDefinitionGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\source\common\string.cpp" />
+    <ClCompile Include="..\..\..\source\common\string_func.cpp" />
     <ClCompile Include="..\..\..\source\skyxengine.cpp" />
     <ClCompile Include="..\..\..\source\SkyXEngine_Build\SkyXEngine_Build.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\..\source\common\string.h" />
+    <ClInclude Include="..\..\..\source\common\string_func.h" />
     <ClInclude Include="..\..\..\source\gdefines.h" />
     <ClInclude Include="..\..\..\source\GRegisterIndex.h" />
     <ClInclude Include="..\..\..\source\SkyXEngine.h" />
diff --git a/proj/SkyXEngine/vs2013/SkyXEngine.vcxproj.filters b/proj/SkyXEngine/vs2013/SkyXEngine.vcxproj.filters
index 087531ce94fd734db4a0c037ec5db57054c6b5e3..72e4611f7a8048d9fb4f743a7b750c962dee6cc5 100644
--- a/proj/SkyXEngine/vs2013/SkyXEngine.vcxproj.filters
+++ b/proj/SkyXEngine/vs2013/SkyXEngine.vcxproj.filters
@@ -10,6 +10,9 @@
     <ClCompile Include="..\..\..\source\skyxengine.cpp">
       <Filter>Source</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\source\common\string_func.cpp">
+      <Filter>Source</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <Filter Include="Header">
@@ -38,6 +41,9 @@
     <ClInclude Include="..\..\..\source\GRegisterIndex.h">
       <Filter>Header</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\..\source\common\string_func.h">
+      <Filter>Header</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="..\..\..\source\SkyXEngine_Build\SkyXEngine.rc">
diff --git a/proj/sxscore/vs2013/sxscore.vcxproj b/proj/sxscore/vs2013/sxscore.vcxproj
index fdc0b888f7270c2ff394451b01c24e8bf2cfb49d..d1bc03c5c7364043f1fb322b6a2e93ed3a7600c0 100644
--- a/proj/sxscore/vs2013/sxscore.vcxproj
+++ b/proj/sxscore/vs2013/sxscore.vcxproj
@@ -11,11 +11,15 @@
     </ProjectConfiguration>
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="..\..\..\source\common\string.cpp" />
+    <ClCompile Include="..\..\..\source\common\string_func.cpp" />
     <ClCompile Include="..\..\..\source\score\sound.cpp" />
     <ClCompile Include="..\..\..\source\score\sxscore.cpp" />
     <ClCompile Include="..\..\..\source\score\sxscore_dll.cpp" />
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="..\..\..\source\common\array.h" />
+    <ClInclude Include="..\..\..\source\common\string_func.h" />
     <ClInclude Include="..\..\..\source\score\sound.h" />
     <ClInclude Include="..\..\..\source\score\sxscore.h" />
   </ItemGroup>
diff --git a/proj/sxscore/vs2013/sxscore.vcxproj.filters b/proj/sxscore/vs2013/sxscore.vcxproj.filters
index 8af11aed22310378c8b210782c5499bc369e0a90..4a0cc44c93b8946e32cda4a89ec3607e351ef740 100644
--- a/proj/sxscore/vs2013/sxscore.vcxproj.filters
+++ b/proj/sxscore/vs2013/sxscore.vcxproj.filters
@@ -24,6 +24,12 @@
     <ClCompile Include="..\..\..\source\score\sound.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\source\common\string.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\source\common\string_func.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\..\source\score\sxscore.h">
@@ -32,5 +38,11 @@
     <ClInclude Include="..\..\..\source\score\sound.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\..\source\common\string_func.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\source\common\array.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/source/SkyXEngine.h b/source/SkyXEngine.h
index 36810e6f94fdb1402609b062236c2e34dfa30b4f..449e335d7fc9a292ba4e7aaece36d6687b0c63a6 100644
--- a/source/SkyXEngine.h
+++ b/source/SkyXEngine.h
@@ -1,160 +1,160 @@
-
-/***********************************************************
-Copyright © Vitaliy Buturlin, Evgeny Danilovich, 2017, 2018
-See the license in LICENSE
-***********************************************************/
-
-/*! 
-\file
-Заголовочный файл движка SkyXEngine, подключает все необходимые библиотеки
-*/
-
+
+/***********************************************************
+Copyright © Vitaliy Buturlin, Evgeny Danilovich, 2017, 2018
+See the license in LICENSE
+***********************************************************/
+
+/*! 
+\file
+Заголовочный файл движка SkyXEngine, подключает все необходимые библиотеки
+*/
+
 /*!
 \mainpage Документация SkyXEngine
 Это документация API (интерфейса программирования приложения) 3D движка real-time рендера SkyXEngine. \n
 Для того чтобы понять что такое SkyXEngine рекомендуем Вам ознакомится с \ref info_engine "кратким описанием движка". \n
 Также было бы крайне полезным узнать \ref general_info_libs "об организации библиотек". \n
 Дальнейшее ознакомление с движком SkyXEngine можно по <a href="./modules.html">документации, которая представлена модулями/подмодулями</a>.
-*/
-
-/*! \page info_engine Информация о движке SkyXEngine
-\tableofcontents
-\section ie_common Общее
-\b SkyXEngine - движок для создания 3D игр с real-time рендером, использует технологии DirectX 9. \n
-<small>Сразу уточнение, DirectX 9 мы используем в связи с личными предпочтениями, так как на наш взгляд эта технология является одной из лучших, хоть и считается устаревшей. 
-Все новое это забытое старое)) И как нам кажется ... нет ничего такого, чего нельзя было бы сделать на DirectX 9, но что можно сделать на другом GAPI, для создания игр любого жанра с real-time рендером.
-Но это только точка зрения нашей команды и она может быть ошибочная. Однако в планах есть расширение поддерживаемых GAPI.</small>
-
-<b>Формирование уровня</b> осуществляется посредством:
- - загрузки статических моделей формата dse, с их автоматическим разбиением на "куски рендера" как quad или octo дерево, возможны сохранение/загрузка в бинарный файл всей геометрии уровня
- - генерации растительности по маске, возможны 2 вида: трава (чем дальше тем меньше размер объекта) и деревья (с возможностью загрузки лодов), возможны возможны сохранение/загрузка в бинарный файл всей растительности уровня. Ручная расстановка расстительности поддерживается. Редактирование поддерживается.
-
-<b>Освещение</b> представлено 3 видами источников света (опционально поддерживается генерация теней от каждого исчтоника света):
- - глобальный (солнце), тени - PSSM
- - локальный - точечный, тени - Cube Shadow Mapping
- - локальный - направленный, тени - Shadow Mapping. 
-
-HDR эффект присутсвует.
-
-<b>Система материалов</b> pbr, то есть построенная на физичеки корретных, но апроксимированных вычислениях. \n
-Для формирования данных для освещения используется техника Deferred shading, что позволяет обрабатывать неограниченное количество источников света. \n
-Поддерживаются отражения 2 видов:
- - плоские (планарные)
- - объемные (кубические). 
-
-Поддерживается до 3 полупрозрачных поверхностей в кадре (пока только тестовый режим, в планах улучшения качества). \n
-Поддерживаемые эффекты поверхностей:
- - микрорельеф
- - микрорельеф по маске (до 4 текстур)
- - детальность
- - детальность по маске (до 4 текстур)
- - комбинированный микрорельеф с детальностью по маске (до 4 текстур)
- - альфа тест
- - просвечиваемость (для освещения тонких поверхностей, к примеру листвы и травы).
-
- Вся система материалов является открытой и практически любой функционал системы доступен для собственной интерпретации, посредством шейдеров. Имеется встроенный набор данных.\n
- Поддерживаются различные пользовательские данные которые интерпретируются только создающим материалы.
- Настрока физического материала доступна.
-
-<b>Постпроцесс</b> состоит из эффектов:
- - черно-белое изображение
- - эффект сепия
- - коррекция изображения
- - рендер солнца
- - bloom
- - lens flare, эффект восприятия яркого света линзами
- - depth of field, глубина резкости
- - linear fog, линейный туман
- - space screen ambient occulusion, глобальное освещение (точнее затенение) в пространстве экрана
- - motion blur, размытие в движении
- - nfaa
- - dlaa.
-
-<b>Декали</b> - следы от пуль, взрывов, трещины. Рисуются поверх основной геометрии.
-
-<b>Физика</b> - для симуляции физики используется физический движок Bullet.
-
-<b>Звуковой движок</b> поддерживает воспроизведение в пространстве и в фоне. Поддерживаемые форматы ogg, wav. Доступно создание инстансов без возможности управления.
-
-<b>Партиклы</b> с необходимым набором логики и с многочисленными и простыми настроками.
-
-<b>AI сетка</b> для навигации живых игровых объектов.
-
-<b>Игровой движок</b> - основа для построения игровой логики. Предоставляет набор игровых объектов и обеспечивает их взаимодействие.
-
-<b>Эффекты окружения</b> представлены фоновыми ambient звуками, погодой, определяемой для каждого уровня, с различными погодными эффектами.
-
-<b>Real-time конфигурация (cvars)</b> позволяет в режиме реального времени через консоль изменять разного рода установки движка
-
-<b>Редакторы:</b> 
- - \link level_editor SXLevelEditor - редактор уровней \endlink \n
- - \link material_editor SXMaterialEditor - редактор материалов \endlink \n
- - \link particles_editor SXParticlesEditor - редактор партиклов \endlink \n
-
-\section dogma_engine Идеология движка
-Основной технической идеей при разработке движка была идея о том что программист должен иметь контроль над объектами которыми он оперирует, НО этот контроль должен быть в меру. \n
-Основной идеей предназначения служила и служит идея о том чтобы предоставляемый инструментарий мог полностью удовлетворять потребностям разработчика, без необходимости со стороны разработчика вникать в детали реализации, но чтобы этот инструментарий имел прозрачную, открытую, свободную, бесплатную лицензию, и разработчик мог спокойно податься в стихию сотворения своего мира. \n
-Также главенствовал принцип разделения функционала на логические блоки (библиотеки) и после окончания разработки очередного блока он бы выносился в dll (с глаз долой). 
-Однако существенным дополнением являлась идея о том что библиотеки не должны ничего значть о равнозначных себе библиотеках в общей иерархии.
-К примеру \ref sxgeom "библиотека статической геометрии и растительности" ничего не знает о \ref sxmtllight "библиотеке материалов", и последняя ничего не знает о первой, однако первая использует функции из второй посредством графического ядра, а вторая осуществляется настройку материалов перед рендером первой.\n
-Немаловажным моментом являлся ориентир на гибкость. К примеру  \ref sxgcore_redefinition_func "переопредляемые функции" в графическом ядре, позволяют настроить на свой лад рендер. \n
-Ну и пожалуй самая главная идея заключается в полноценной возможности разработки игр с видом от первого лица, с настройкой/перестройкой "под себя" всего рендера. Также к приправе к этому мы руководствовались мыслью о том что скриптеры (коих не мало) могли бы вести разработку игры на своем (доступном им) уровне, со всеми возможностями движка.
-
-\section struct_engine Структура движка
-Весь движок состоит из \ref general_info_libs "подсистем", которые в некоторых случаях являются ядрами. \n
-Иерархия подсистем:\n
-\- \ref sxcore\n
-\-- \ref sxgcore\n
-\--- \ref sxgeom\n
-\--- \ref sxanim\n
-\--- \ref sxmtllight\n
-\--- \ref sxpp\n
-\- \ref sxinput\n
-Все библиотеки представлены файлами dll, что позволяет разделить функционал и реализацию. Также в большинстве случаев библиотеки могут быть вычленены из самого движка и могут использоваться автономно.\n
-В большинстве случаев весь функционал библиотек предоставляется интерфейсом функций, а идентификация объектов числовая, по типу #ID.
-Это позволяет не беспокоится о типах и о существовании объектов - об этом заботятся сами библиотеки.
-*/
-
-/*! \page std_doc Стандарт документирования
-\tableofcontents
-\section std_doc_common Общее
-Дабы создать удобочитаемые комментрии, которые легко бы трансформировались в документацию был создан данный стандарт документирования, следование которому является обязательным.
-Так как для документирования был выбран Doxygen, то все что касается документирования будет в контексте именно этой программы. \n
-Для более чектого структурирования  необходимо разделять весь код на логические звенья, которые могут быть представлены модулями/подмодулями и группами как в модулях так и вне их. 
-
-\section style_doc Стиль документирования
+*/
+
+/*! \page info_engine Информация о движке SkyXEngine
+\tableofcontents
+\section ie_common Общее
+\b SkyXEngine - движок для создания 3D игр с real-time рендером, использует технологии DirectX 9. \n
+<small>Сразу уточнение, DirectX 9 мы используем в связи с личными предпочтениями, так как на наш взгляд эта технология является одной из лучших, хоть и считается устаревшей. 
+Все новое это забытое старое)) И как нам кажется ... нет ничего такого, чего нельзя было бы сделать на DirectX 9, но что можно сделать на другом GAPI, для создания игр любого жанра с real-time рендером.
+Но это только точка зрения нашей команды и она может быть ошибочная. Однако в планах есть расширение поддерживаемых GAPI.</small>
+
+<b>Формирование уровня</b> осуществляется посредством:
+ - загрузки статических моделей формата dse, с их автоматическим разбиением на "куски рендера" как quad или octo дерево, возможны сохранение/загрузка в бинарный файл всей геометрии уровня
+ - генерации растительности по маске, возможны 2 вида: трава (чем дальше тем меньше размер объекта) и деревья (с возможностью загрузки лодов), возможны возможны сохранение/загрузка в бинарный файл всей растительности уровня. Ручная расстановка расстительности поддерживается. Редактирование поддерживается.
+
+<b>Освещение</b> представлено 3 видами источников света (опционально поддерживается генерация теней от каждого исчтоника света):
+ - глобальный (солнце), тени - PSSM
+ - локальный - точечный, тени - Cube Shadow Mapping
+ - локальный - направленный, тени - Shadow Mapping. 
+
+HDR эффект присутсвует.
+
+<b>Система материалов</b> pbr, то есть построенная на физичеки корретных, но апроксимированных вычислениях. \n
+Для формирования данных для освещения используется техника Deferred shading, что позволяет обрабатывать неограниченное количество источников света. \n
+Поддерживаются отражения 2 видов:
+ - плоские (планарные)
+ - объемные (кубические). 
+
+Поддерживается до 3 полупрозрачных поверхностей в кадре (пока только тестовый режим, в планах улучшения качества). \n
+Поддерживаемые эффекты поверхностей:
+ - микрорельеф
+ - микрорельеф по маске (до 4 текстур)
+ - детальность
+ - детальность по маске (до 4 текстур)
+ - комбинированный микрорельеф с детальностью по маске (до 4 текстур)
+ - альфа тест
+ - просвечиваемость (для освещения тонких поверхностей, к примеру листвы и травы).
+
+ Вся система материалов является открытой и практически любой функционал системы доступен для собственной интерпретации, посредством шейдеров. Имеется встроенный набор данных.\n
+ Поддерживаются различные пользовательские данные которые интерпретируются только создающим материалы.
+ Настрока физического материала доступна.
+
+<b>Постпроцесс</b> состоит из эффектов:
+ - черно-белое изображение
+ - эффект сепия
+ - коррекция изображения
+ - рендер солнца
+ - bloom
+ - lens flare, эффект восприятия яркого света линзами
+ - depth of field, глубина резкости
+ - linear fog, линейный туман
+ - space screen ambient occulusion, глобальное освещение (точнее затенение) в пространстве экрана
+ - motion blur, размытие в движении
+ - nfaa
+ - dlaa.
+
+<b>Декали</b> - следы от пуль, взрывов, трещины. Рисуются поверх основной геометрии.
+
+<b>Физика</b> - для симуляции физики используется физический движок Bullet.
+
+<b>Звуковой движок</b> поддерживает воспроизведение в пространстве и в фоне. Поддерживаемые форматы ogg, wav. Доступно создание инстансов без возможности управления.
+
+<b>Партиклы</b> с необходимым набором логики и с многочисленными и простыми настроками.
+
+<b>AI сетка</b> для навигации живых игровых объектов.
+
+<b>Игровой движок</b> - основа для построения игровой логики. Предоставляет набор игровых объектов и обеспечивает их взаимодействие.
+
+<b>Эффекты окружения</b> представлены фоновыми ambient звуками, погодой, определяемой для каждого уровня, с различными погодными эффектами.
+
+<b>Real-time конфигурация (cvars)</b> позволяет в режиме реального времени через консоль изменять разного рода установки движка
+
+<b>Редакторы:</b> 
+ - \link level_editor SXLevelEditor - редактор уровней \endlink \n
+ - \link material_editor SXMaterialEditor - редактор материалов \endlink \n
+ - \link particles_editor SXParticlesEditor - редактор партиклов \endlink \n
+
+\section dogma_engine Идеология движка
+Основной технической идеей при разработке движка была идея о том что программист должен иметь контроль над объектами которыми он оперирует, НО этот контроль должен быть в меру. \n
+Основной идеей предназначения служила и служит идея о том чтобы предоставляемый инструментарий мог полностью удовлетворять потребностям разработчика, без необходимости со стороны разработчика вникать в детали реализации, но чтобы этот инструментарий имел прозрачную, открытую, свободную, бесплатную лицензию, и разработчик мог спокойно податься в стихию сотворения своего мира. \n
+Также главенствовал принцип разделения функционала на логические блоки (библиотеки) и после окончания разработки очередного блока он бы выносился в dll (с глаз долой). 
+Однако существенным дополнением являлась идея о том что библиотеки не должны ничего значть о равнозначных себе библиотеках в общей иерархии.
+К примеру \ref sxgeom "библиотека статической геометрии и растительности" ничего не знает о \ref sxmtllight "библиотеке материалов", и последняя ничего не знает о первой, однако первая использует функции из второй посредством графического ядра, а вторая осуществляется настройку материалов перед рендером первой.\n
+Немаловажным моментом являлся ориентир на гибкость. К примеру  \ref sxgcore_redefinition_func "переопредляемые функции" в графическом ядре, позволяют настроить на свой лад рендер. \n
+Ну и пожалуй самая главная идея заключается в полноценной возможности разработки игр с видом от первого лица, с настройкой/перестройкой "под себя" всего рендера. Также к приправе к этому мы руководствовались мыслью о том что скриптеры (коих не мало) могли бы вести разработку игры на своем (доступном им) уровне, со всеми возможностями движка.
+
+\section struct_engine Структура движка
+Весь движок состоит из \ref general_info_libs "подсистем", которые в некоторых случаях являются ядрами. \n
+Иерархия подсистем:\n
+\- \ref sxcore\n
+\-- \ref sxgcore\n
+\--- \ref sxgeom\n
+\--- \ref sxanim\n
+\--- \ref sxmtllight\n
+\--- \ref sxpp\n
+\- \ref sxinput\n
+Все библиотеки представлены файлами dll, что позволяет разделить функционал и реализацию. Также в большинстве случаев библиотеки могут быть вычленены из самого движка и могут использоваться автономно.\n
+В большинстве случаев весь функционал библиотек предоставляется интерфейсом функций, а идентификация объектов числовая, по типу #ID.
+Это позволяет не беспокоится о типах и о существовании объектов - об этом заботятся сами библиотеки.
+*/
+
+/*! \page std_doc Стандарт документирования
+\tableofcontents
+\section std_doc_common Общее
+Дабы создать удобочитаемые комментрии, которые легко бы трансформировались в документацию был создан данный стандарт документирования, следование которому является обязательным.
+Так как для документирования был выбран Doxygen, то все что касается документирования будет в контексте именно этой программы. \n
+Для более чектого структурирования  необходимо разделять весь код на логические звенья, которые могут быть представлены модулями/подмодулями и группами как в модулях так и вне их. 
+
+\section style_doc Стиль документирования
 QT стиль документирования (!) и QT_AUTOBRIEF - короткая документация до точки в любом комментарии, а после точки идет подробное документирование если надо.\n
 Возможные виды:
 <pre>
 //! документирование того что идет за этой строкой 
 //!< документирование того что предшествовало данному комментарию
 / *! документирование того что идет за этой строкой * /
-/ *!< документирование того что предшествовало данному комментарию * /
-</pre>
-<b>Примечание:</b> здесь и далее / * и * / комментарий без пробелов!
-
+/ *!< документирование того что предшествовало данному комментарию * /
+</pre>
+<b>Примечание:</b> здесь и далее / * и * / комментарий без пробелов!
+
 \section style_desc_file Описание файла (обязательно для каждого документируемого файла)
 <pre>
 / *!
 \\file
 Описание файла
-\* /
-</pre>
-
+\* /
+</pre>
+
 \section style_modules Модули/подмодули
 <pre>
 / *! \\defgroup имя_модуля описание модуля
 \@{
 \* /
 ... код модуля
-//!\@} имя_модуля
-</pre>
-В случае если модуль является подмодулем другого модуля то после описания модуля необходимо добавить:
-<pre>
- \\ingroup имя_модуля_которому_будет_принадлежать_данный_модуль
-</pre>
-Окончание модуля может быть любым удобным, но только окончание модуля должно включать в себя имя модуля для которого написан конец.
-
+//!\@} имя_модуля
+</pre>
+В случае если модуль является подмодулем другого модуля то после описания модуля необходимо добавить:
+<pre>
+ \\ingroup имя_модуля_которому_будет_принадлежать_данный_модуль
+</pre>
+Окончание модуля может быть любым удобным, но только окончание модуля должно включать в себя имя модуля для которого написан конец.
+
 \section style_group Группа (вложенные группы не поддерживаются)
 <pre>
 / *! \\name название группы, оно также будет размещено в документации
@@ -163,55 +163,55 @@ QT стиль документирования (!) и QT_AUTOBRIEF - корот
 //! \@{
 ... все кроме классов
 //! \@}
-</pre>
-
-\section style_ref Ссылки
-Для лучшей навигации необходимо использовать ссылки, которые могут указывать на структурные единицы (модули/подмодули, страницы, секции) так и на код.
-Пример ссылки на структурные единицы:
-<pre>
-Весь движок состоит из \\ref general_info_libs "подсистем".
-</pre>
-Или без указания имени ссылки:
-<pre>
-\\ref sxcore
-</pre>
-
-Пример ссылки на код:
-<pre>
-\#SCore_Create
-</pre>
-
-\section style_page Страницы
-<pre>
-/ *! \\page идентификатор_только_латиница Заголовок страницы
-\\tableofcontents
-Для того чтобы разделить на разделы можно использовать секции:
-\\section style_page Создание страниц
-\* /
-</pre>
-
-\section style_list Списки
-<pre>
- \- первый элемент
- \- второй элемент
-</pre>
-
-\section style_extra Дополнительно
-\\n - для новой строки \n
-Также можно использовать html теги. \n
-\\note - заметка  \n
-\\warning - предупреждение  \n
-\\todo - пометка о том что надо сделать  \n
-*/
-
-//#############################################################################
-
-/*! \page engine_cvar Движковые квары
-\tableofcontents
-
-\section engine_cvar_naming Правила именования
-Все имена кваров пишутся только в нижнем регистре, в качестве пробела используется _ (нижний пробел).
-Если квар является дефолтным, относительно него буду происходит расчеты либо действия, то тогда prefix_default_cvar.
+</pre>
+
+\section style_ref Ссылки
+Для лучшей навигации необходимо использовать ссылки, которые могут указывать на структурные единицы (модули/подмодули, страницы, секции) так и на код.
+Пример ссылки на структурные единицы:
+<pre>
+Весь движок состоит из \\ref general_info_libs "подсистем".
+</pre>
+Или без указания имени ссылки:
+<pre>
+\\ref sxcore
+</pre>
+
+Пример ссылки на код:
+<pre>
+\#SCore_Create
+</pre>
+
+\section style_page Страницы
+<pre>
+/ *! \\page идентификатор_только_латиница Заголовок страницы
+\\tableofcontents
+Для того чтобы разделить на разделы можно использовать секции:
+\\section style_page Создание страниц
+\* /
+</pre>
+
+\section style_list Списки
+<pre>
+ \- первый элемент
+ \- второй элемент
+</pre>
+
+\section style_extra Дополнительно
+\\n - для новой строки \n
+Также можно использовать html теги. \n
+\\note - заметка  \n
+\\warning - предупреждение  \n
+\\todo - пометка о том что надо сделать  \n
+*/
+
+//#############################################################################
+
+/*! \page engine_cvar Движковые квары
+\tableofcontents
+
+\section engine_cvar_naming Правила именования
+Все имена кваров пишутся только в нижнем регистре, в качестве пробела используется _ (нижний пробел).
+Если квар является дефолтным, относительно него буду происходит расчеты либо действия, то тогда prefix_default_cvar.
  - r_  - все, что связано с рендером непосредственно
  - cl_ - игрок управление
  - phy_ - физика
@@ -224,21 +224,21 @@ QT стиль документирования (!) и QT_AUTOBRIEF - корот
  - nav_ - навигация
  - snd_ - звуки
  - ed_ - для редакторов
- - pt_ - партиклы
-
- \section engine_cvar_camera Камера
- - \b r_default_fov дефолтный fov
- - \b r_near ближняя плоскость отсечения
- - \b r_far дальняя плоскость отсечения
-
-\section engine_cvar_window Окно
- - \b r_win_width размер окна по горизонтали (в пикселях)
- - \b r_win_height размер окна по вертикали (в пикселях)
- - \b r_win_windowed режим рендера true - оконный, false - полноэкранный
- - \b r_final_image тип финального (выводимого в окно рендера) изображения из перечисления DS_RT
- - \b r_resize тип изменения размеров окан рендера из перечисления RENDER_RESIZE
-
-\section engine_cvar_pp Post process
+ - pt_ - партиклы
+
+ \section engine_cvar_camera Камера
+ - \b r_default_fov дефолтный fov
+ - \b r_near ближняя плоскость отсечения
+ - \b r_far дальняя плоскость отсечения
+
+\section engine_cvar_window Окно
+ - \b r_win_width размер окна по горизонтали (в пикселях)
+ - \b r_win_height размер окна по вертикали (в пикселях)
+ - \b r_win_windowed режим рендера true - оконный, false - полноэкранный
+ - \b r_final_image тип финального (выводимого в окно рендера) изображения из перечисления DS_RT
+ - \b r_resize тип изменения размеров окан рендера из перечисления RENDER_RESIZE
+
+\section engine_cvar_pp Post process
  - \b pp_ssao установка качества ssao (0 - не рисовать, 1 - среднее, 2 - хорошее, 3 - высокое)
  - \b pp_bloom рисовать ли эффект bloom (true/false)
  - \b pp_lensflare true рисовать ли эффект lens flare (true/false)
@@ -262,270 +262,271 @@ QT стиль документирования (!) и QT_AUTOBRIEF - корот
  - \b r_green_lod0 дистанция от наблюдателя на которой заканчивается нулевой лод растительности (он же лод травы), то есть дальность отрисовки травы (0,100)
  - \b r_green_lod1 дистанция от наблюдателя на которой заканчивается первый лод растительности (50,150)
  - \b r_green_less дистанция от наблюдателя c которой начнет уменьшаться трава (0,green_lod0)
-
- \section engine_cvar_texfilter Фильтрация текстур 
+
+ \section engine_cvar_texfilter Фильтрация текстур 
  - \b r_texfilter_type тип фильтрации текстур, 0 - точечная, 1 - линейная, 2 - анизотропная
  - \b r_texfilter_max_anisotropy максимальное значение анизотропной фильтрации (если включена) [1,16]
- - \b r_texfilter_max_miplevel какой mip уровень текстур использовать? 0 - самый высокий, 1 - ниже на один уровень и т.д.
- - \b r_stats показывать ли статистику? 0 - нет, 1 - fps и игровое время, 2 - показать полностью
-
-\section engine_cvar_env Окружение
-  - \b env_default_rain_density коэфициент плотности дождя (0,1]
-  - \b env_default_thunderbolt могут ли воспроизводится эффекты молнии?
-  - \b env_weather_snd_volume громкость звуков погоды [0,1]
-  - \b env_ambient_snd_volume громкость фоновых звуков на уровне [0,1]
-
-\section engine_cvar_game Игра
-  - \b g_time_run запущено ли игрвоое время?"
-  - \b g_time_speed скорость/соотношение течения игрового времени
-
-//##########################################################################
-
-\page editors Редакторы
-\link level_editor SXLevelEditor - редактор уровней \endlink \n
-\link material_editor SXMaterialEditor - редактор материалов \endlink \n 
-\link particles_editor SXParticlesEditor - редактор партиклов \endlink \n
-*/
-
-//#############################################################################
-
-#ifndef __SKYXENGINE_H
-#define __SKYXENGINE_H
-
-#define SKYXENGINE_VERSION "0.9.3"
-
-#include <windows.h>
-#include <ctime>
-#include <gdefines.h>
-#include <common/array.h>
-#include <common/string.h>
-#include <fstream>
-
-//ЗАГРУЗКА БИБЛИОТЕК
-//{
-#if defined(_DEBUG)
-#pragma comment(lib, "sxcore_d.lib")
-#else
-#pragma comment(lib, "sxcore.lib")
-#endif
-#include <core/sxcore.h>
-
-#if defined(_DEBUG)
-#pragma comment(lib, "sxinput_d.lib")
-#else
-#pragma comment(lib, "sxinput.lib")
-#endif
-#include <input/sxinput.h>
-
-#if defined(_DEBUG)
-#pragma comment(lib, "sxscore_d.lib")
-#else
-#pragma comment(lib, "sxscore.lib")
-#endif
-#include <score/sxscore.h>
-
-#if defined(_DEBUG)
-#pragma comment(lib, "sxgcore_d.lib")
-#else
-#pragma comment(lib, "sxgcore.lib")
-#endif
-#include <gcore/sxgcore.h>
-
-#if defined(_DEBUG)
-#pragma comment(lib, "sxgeom_d.lib")
-#else
-#pragma comment(lib, "sxgeom.lib")
-#endif
-#include <geom/sxgeom.h>
-
-#if defined(_DEBUG)
-#pragma comment(lib, "sxmtllight_d.lib")
-#else
-#pragma comment(lib, "sxmtllight.lib")
-#endif
-#include <mtllight/sxmtllight.h>
-
-#if defined(_DEBUG)
-#pragma comment(lib, "sxparticles_d.lib")
-#else
-#pragma comment(lib, "sxparticles.lib")
-#endif
-#include <particles/sxparticles.h>
-
-#if defined(_DEBUG)
-#pragma comment(lib, "sxpp_d.lib")
-#else
-#pragma comment(lib, "sxpp.lib")
-#endif
-#include <pp/sxpp.h>
-
-#if defined(_DEBUG)
-#pragma comment(lib, "sxanim_d.lib")
-#else
-#pragma comment(lib, "sxanim.lib")
-#endif
-#include <anim/sxanim.h>
-
-#if defined(_DEBUG)
-#pragma comment(lib, "sxphysics_d.lib")
-#else
-#pragma comment(lib, "sxphysics.lib")
-#endif
-#include <physics/sxphysics.h>
-
-#if defined(_DEBUG)
-#pragma comment(lib, "sxaigrid_d.lib")
-#else
-#pragma comment(lib, "sxaigrid.lib")
-#endif
-#include <aigrid/sxaigrid.h>
-
-#if defined(_DEBUG)
-#pragma comment(lib, "sxdecals_d.lib")
-#else
-#pragma comment(lib, "sxdecals.lib")
-#endif
-#include <decals/sxdecals.h>
-
-#if defined(_DEBUG)
-#pragma comment(lib, "sxlevel_d.lib")
-#else
-#pragma comment(lib, "sxlevel.lib")
-#endif
-#include <level/sxlevel.h>
-
-#if defined(_DEBUG)
-#pragma comment(lib, "sxgame_d.lib")
-#else
-#pragma comment(lib, "sxgame.lib")
-#endif
-#include <game/sxgame.h>
-
+ - \b r_texfilter_max_miplevel какой mip уровень текстур использовать? 0 - самый высокий, 1 - ниже на один уровень и т.д.
+ - \b r_stats показывать ли статистику? 0 - нет, 1 - fps и игровое время, 2 - показать полностью
+
+\section engine_cvar_env Окружение
+  - \b env_default_rain_density коэфициент плотности дождя (0,1]
+  - \b env_default_thunderbolt могут ли воспроизводится эффекты молнии?
+  - \b env_weather_snd_volume громкость звуков погоды [0,1]
+  - \b env_ambient_snd_volume громкость фоновых звуков на уровне [0,1]
+
+\section engine_cvar_game Игра
+  - \b g_time_run запущено ли игрвоое время?"
+  - \b g_time_speed скорость/соотношение течения игрового времени
+
+//##########################################################################
+
+\page editors Редакторы
+\link level_editor SXLevelEditor - редактор уровней \endlink \n
+\link material_editor SXMaterialEditor - редактор материалов \endlink \n 
+\link particles_editor SXParticlesEditor - редактор партиклов \endlink \n
+*/
+
+//#############################################################################
+
+#ifndef __SKYXENGINE_H
+#define __SKYXENGINE_H
+
+#define SKYXENGINE_VERSION "0.9.3"
+
+#include <vld.h>
+#include <windows.h>
+#include <ctime>
+#include <gdefines.h>
+#include <common/array.h>
+#include <common/string.h>
+#include <fstream>
+
+//ЗАГРУЗКА БИБЛИОТЕК
+//{
+#if defined(_DEBUG)
+#pragma comment(lib, "sxcore_d.lib")
+#else
+#pragma comment(lib, "sxcore.lib")
+#endif
+#include <core/sxcore.h>
+
+#if defined(_DEBUG)
+#pragma comment(lib, "sxinput_d.lib")
+#else
+#pragma comment(lib, "sxinput.lib")
+#endif
+#include <input/sxinput.h>
+
+#if defined(_DEBUG)
+#pragma comment(lib, "sxscore_d.lib")
+#else
+#pragma comment(lib, "sxscore.lib")
+#endif
+#include <score/sxscore.h>
+
+#if defined(_DEBUG)
+#pragma comment(lib, "sxgcore_d.lib")
+#else
+#pragma comment(lib, "sxgcore.lib")
+#endif
+#include <gcore/sxgcore.h>
+
+#if defined(_DEBUG)
+#pragma comment(lib, "sxgeom_d.lib")
+#else
+#pragma comment(lib, "sxgeom.lib")
+#endif
+#include <geom/sxgeom.h>
+
+#if defined(_DEBUG)
+#pragma comment(lib, "sxmtllight_d.lib")
+#else
+#pragma comment(lib, "sxmtllight.lib")
+#endif
+#include <mtllight/sxmtllight.h>
+
+#if defined(_DEBUG)
+#pragma comment(lib, "sxparticles_d.lib")
+#else
+#pragma comment(lib, "sxparticles.lib")
+#endif
+#include <particles/sxparticles.h>
+
+#if defined(_DEBUG)
+#pragma comment(lib, "sxpp_d.lib")
+#else
+#pragma comment(lib, "sxpp.lib")
+#endif
+#include <pp/sxpp.h>
+
+#if defined(_DEBUG)
+#pragma comment(lib, "sxanim_d.lib")
+#else
+#pragma comment(lib, "sxanim.lib")
+#endif
+#include <anim/sxanim.h>
+
+#if defined(_DEBUG)
+#pragma comment(lib, "sxphysics_d.lib")
+#else
+#pragma comment(lib, "sxphysics.lib")
+#endif
+#include <physics/sxphysics.h>
+
+#if defined(_DEBUG)
+#pragma comment(lib, "sxaigrid_d.lib")
+#else
+#pragma comment(lib, "sxaigrid.lib")
+#endif
+#include <aigrid/sxaigrid.h>
+
+#if defined(_DEBUG)
+#pragma comment(lib, "sxdecals_d.lib")
+#else
+#pragma comment(lib, "sxdecals.lib")
+#endif
+#include <decals/sxdecals.h>
+
+#if defined(_DEBUG)
+#pragma comment(lib, "sxlevel_d.lib")
+#else
+#pragma comment(lib, "sxlevel.lib")
+#endif
+#include <level/sxlevel.h>
+
+#if defined(_DEBUG)
+#pragma comment(lib, "sxgame_d.lib")
+#else
+#pragma comment(lib, "sxgame.lib")
+#endif
+#include <game/sxgame.h>
+
 #if defined(SX_LEVEL_EDITOR) || defined(SX_MATERIAL_EDITOR) || defined(SX_PARTICLES_EDITOR)
-#if defined(_DEBUG)
-#pragma comment(lib, "sxguiwinapi_d.lib")
-#else
-#pragma comment(lib, "sxguiwinapi.lib")
-#endif
-#include <sxguiwinapi/sxgui.h>
-#endif
-
-#if defined(_DEBUG)
-#pragma comment(lib, "sxrender_d.lib")
-#else
-#pragma comment(lib, "sxrender.lib")
-#endif
-#include <render/sxrender.h>
-
-//}
-
-//#############################################################################
-
-#if defined(SX_GAME)
-#include <SkyXEngine_Build/resource.h>
-#endif
-
-#if defined(SX_LEVEL_EDITOR)
-#include <SXLevelEditor/resource.h>
-#include <SXLevelEditor/level_editor.h>
-#endif
-
-#if defined(SX_MATERIAL_EDITOR)
-#include <sxmaterialeditor/resource.h>
-#include <sxmaterialeditor/material_editor.h>
-#endif
-
-#if defined(SX_PARTICLES_EDITOR)
-#include <sxparticleseditor/resource.h>
-#include <sxparticleseditor/particles_editor.h>
-#endif
-
-//#############################################################################
-
-/*! \defgroup skyxengine Функции и данные движка
-@{*/
-
-//! инициализация движка
-void SkyXEngine_Init(HWND hWnd3D = 0, HWND hWndParent3D = 0);
-
-//! инициализация путей в регистрах
-void SkyXEngine_InitPaths();
-
-//! создание кваров и загрузка файлов настроек
-void SkyXEngine_CreateLoadCVar();
-
-//! обработчик для окна рендера
-LRESULT CALLBACK SkyXEngine_WndProc(HWND hWnd, UINT uiMessage, WPARAM wParam, LPARAM lParam);
-
-//! создание окна рендера
-HWND SkyXEngine_CreateWindow(const char *szName, const char *szCaption, int iWidth, int iHeight);
-
-//**************************************************************************
-
-//! перебор всех окон процесса для их сворачивания
-BOOL CALLBACK SkyXEngine_EnumWindowsProc(HWND hwnd, LPARAM lParam);
-
-//! обработка ошибки
-void SkyXEngine_HandlerError(const char *szFormat, ...);
-
-//! инициализация потока ведения лога
-void SkyXEngine_InitOutLog();
-
-//! функция ведения лога и обработки сообщений
-void SkyXEngine_PrintfLog(int level, const char *szFormat, ...);
-
-//**************************************************************************
-
-//! кадр
-void SkyXEngine_Frame(DWORD timeDelta);
-
-//! обновление данных кваром (реакция на обновление)
-void SkyXEngind_UpdateDataCVar();
-
-//! запуск основного цикла обработки
-int SkyXEngine_CycleMain();
-
-//! уничтожение данных движка, освобождение памяти
+#if defined(_DEBUG)
+#pragma comment(lib, "sxguiwinapi_d.lib")
+#else
+#pragma comment(lib, "sxguiwinapi.lib")
+#endif
+#include <sxguiwinapi/sxgui.h>
+#endif
+
+#if defined(_DEBUG)
+#pragma comment(lib, "sxrender_d.lib")
+#else
+#pragma comment(lib, "sxrender.lib")
+#endif
+#include <render/sxrender.h>
+
+//}
+
+//#############################################################################
+
+#if defined(SX_GAME)
+#include <SkyXEngine_Build/resource.h>
+#endif
+
+#if defined(SX_LEVEL_EDITOR)
+#include <SXLevelEditor/resource.h>
+#include <SXLevelEditor/level_editor.h>
+#endif
+
+#if defined(SX_MATERIAL_EDITOR)
+#include <sxmaterialeditor/resource.h>
+#include <sxmaterialeditor/material_editor.h>
+#endif
+
+#if defined(SX_PARTICLES_EDITOR)
+#include <sxparticleseditor/resource.h>
+#include <sxparticleseditor/particles_editor.h>
+#endif
+
+//#############################################################################
+
+/*! \defgroup skyxengine Функции и данные движка
+@{*/
+
+//! инициализация движка
+void SkyXEngine_Init(HWND hWnd3D = 0, HWND hWndParent3D = 0);
+
+//! инициализация путей в регистрах
+void SkyXEngine_InitPaths();
+
+//! создание кваров и загрузка файлов настроек
+void SkyXEngine_CreateLoadCVar();
+
+//! обработчик для окна рендера
+LRESULT CALLBACK SkyXEngine_WndProc(HWND hWnd, UINT uiMessage, WPARAM wParam, LPARAM lParam);
+
+//! создание окна рендера
+HWND SkyXEngine_CreateWindow(const char *szName, const char *szCaption, int iWidth, int iHeight);
+
+//**************************************************************************
+
+//! перебор всех окон процесса для их сворачивания
+BOOL CALLBACK SkyXEngine_EnumWindowsProc(HWND hwnd, LPARAM lParam);
+
+//! обработка ошибки
+void SkyXEngine_HandlerError(const char *szFormat, ...);
+
+//! инициализация потока ведения лога
+void SkyXEngine_InitOutLog();
+
+//! функция ведения лога и обработки сообщений
+void SkyXEngine_PrintfLog(int level, const char *szFormat, ...);
+
+//**************************************************************************
+
+//! кадр
+void SkyXEngine_Frame(DWORD timeDelta);
+
+//! обновление данных кваром (реакция на обновление)
+void SkyXEngind_UpdateDataCVar();
+
+//! запуск основного цикла обработки
+int SkyXEngine_CycleMain();
+
+//! уничтожение данных движка, освобождение памяти
 void SkyXEngine_Kill();
 
 //**************************************************************************
 
-/*! \name skyxengine_preview_wnd preview_wnd - Функции превью окна движка
+/*! \name skyxengine_preview_wnd preview_wnd - Функции превью окна движка
 @{*/
 
 //! обработчик для превьюокна
 LRESULT CALLBACK SkyXEngine_PreviewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
-
-//! создание превью окна
-void SkyXEngine_PreviewCreate();
-
-//! уничтожение превью окна
-void SkyXEngine_PreviewKill();
-
-//!@} 
-
-//**************************************************************************
-
-/*! \name skyxengine_redefined_func redefined_func - Функции обертки, для передачи графическому ядру для замены стандартных
+
+//! создание превью окна
+void SkyXEngine_PreviewCreate();
+
+//! уничтожение превью окна
+void SkyXEngine_PreviewKill();
+
+//!@} 
+
+//**************************************************************************
+
+/*! \name skyxengine_redefined_func redefined_func - Функции обертки, для передачи графическому ядру для замены стандартных
 @{*/
 
-//! функция отрисовки, в данной версии не назначается
-void SkyXEngine_RFuncDIP(UINT type_primitive, long base_vertexIndex, UINT min_vertex_index, UINT num_vertices, UINT start_index, UINT prim_count);
-
-//! функция установки материала по id, world - мировая матрица
-void SkyXEngine_RFuncMtlSet(ID id, float4x4* world);
-
-//! функция загрузки материала
-ID SkyXEngine_RFuncMtlLoad(const char* name, int mtl_type);
-
-//! просчет физики для квада аи сетки
-bool SkyXEngine_RFuncAIQuadPhyNavigate(float3_t * pos);
-
-//! просчет столкновения частицы с миром
-bool SkyXEngine_RFuncParticlesPhyCollision(const float3 * lastpos, const float3* nextpos, float3* coll_pos, float3* coll_nrm);
-
-//!@}
-
-//!@} skyxengine
-
+//! функция отрисовки, в данной версии не назначается
+void SkyXEngine_RFuncDIP(UINT type_primitive, long base_vertexIndex, UINT min_vertex_index, UINT num_vertices, UINT start_index, UINT prim_count);
+
+//! функция установки материала по id, world - мировая матрица
+void SkyXEngine_RFuncMtlSet(ID id, float4x4* world);
+
+//! функция загрузки материала
+ID SkyXEngine_RFuncMtlLoad(const char* name, int mtl_type);
+
+//! просчет физики для квада аи сетки
+bool SkyXEngine_RFuncAIQuadPhyNavigate(float3_t * pos);
+
+//! просчет столкновения частицы с миром
+bool SkyXEngine_RFuncParticlesPhyCollision(const float3 * lastpos, const float3* nextpos, float3* coll_pos, float3* coll_nrm);
+
+//!@}
+
+//!@} skyxengine
+
 #endif
\ No newline at end of file
diff --git a/source/SkyXEngine_Build/SkyXEngine_Build.cpp b/source/SkyXEngine_Build/SkyXEngine_Build.cpp
index af579d6be24a02613cd8ef75fb351fda860d0dc2..9b3747b761b2f18b98bb777e2705692d9f199252 100644
--- a/source/SkyXEngine_Build/SkyXEngine_Build.cpp
+++ b/source/SkyXEngine_Build/SkyXEngine_Build.cpp
@@ -7,6 +7,7 @@ See the license in LICENSE
 #define _CRT_SECURE_NO_WARNINGS
 
 #include <SkyXEngine.h>
+//#include <common/string_func.h>
 
 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
 {
diff --git a/source/core/concmd.cpp b/source/core/concmd.cpp
index 0505613bf05d6a442cb54b9127811566f4acd00e..83d5dd55aeb288ff97e6d2ae6cc5bc6270d5486d 100644
--- a/source/core/concmd.cpp
+++ b/source/core/concmd.cpp
@@ -623,9 +623,9 @@ bool CommandConnect()
 	struct addrinfo *result = NULL,
 		*ptr = NULL,
 		hints;
-	char recvbuf[2048];
+	
 	int iResult;
-	int recvbuflen = sizeof(recvbuf);
+	
 
 	// Initialize Winsock
 	iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
diff --git a/source/core/sxcore.cpp b/source/core/sxcore.cpp
index 81c9cdb7c3cb01445f1c5424923428938e3f81bd..46c3c26a22e958f9c65724c3f5df24d36ee4f051 100644
--- a/source/core/sxcore.cpp
+++ b/source/core/sxcore.cpp
@@ -86,7 +86,7 @@ SX_LIB_API UINT Core_0GetTimeLastModify(const char *szPath)
 	if (hFile == INVALID_HANDLE_VALUE)
 		return 0;
 
-	SYSTEMTIME stUTC, stLocal;
+	SYSTEMTIME stUTC;
 	FILETIME ftCreate, ftAccess, ftWrite;
 	GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite);
 	FileTimeToSystemTime(&ftWrite, &stUTC);
diff --git a/source/game/BaseTool.cpp b/source/game/BaseTool.cpp
index 13eab5f9249adb5262a1ed6708675f98b3f88349..8727766bc58c0af04dec11b98a6c5acb3d2258e9 100644
--- a/source/game/BaseTool.cpp
+++ b/source/game/BaseTool.cpp
@@ -84,11 +84,11 @@ void CBaseTool::onPostLoad()
 
 	if(m_szPrimaryActionSound[0])
 	{
-		m_iSoundAction1 = SSCore_SndCreate3dInst(m_szPrimaryActionSound, false, 0, 100);
+		m_iSoundAction1 = SSCore_SndCreate3dInst(m_szPrimaryActionSound, SX_SOUND_CHANNEL_GAME, 100);
 	}
 	if(m_szSecondaryActionSound[0])
 	{
-		m_iSoundAction2 = SSCore_SndCreate3dInst(m_szSecondaryActionSound, false, 0, 100);
+		m_iSoundAction2 = SSCore_SndCreate3dInst(m_szSecondaryActionSound, SX_SOUND_CHANNEL_GAME, 100);
 	}
 	if(m_szPrimaryActionMuzzleflash[0])
 	{
@@ -122,7 +122,7 @@ void CBaseTool::primaryAction(BOOL st)
 		}
 		if(ID_VALID(m_iSoundAction1))
 		{
-			SSCore_SndInstancePlay3d(m_iSoundAction1, &getPos());
+			SSCore_SndInstancePlay3d(m_iSoundAction1, false, false, &getPos());
 		}
 
 		//((CPlayer*)m_pOwner)->is
diff --git a/source/game/BaseWeapon.cpp b/source/game/BaseWeapon.cpp
index 9dc7dd01ef53a8ad03e6b1d9b8b7ef170ba8cb74..1a60954b21cfc19b0d80d72e01097debfff4954f 100644
--- a/source/game/BaseWeapon.cpp
+++ b/source/game/BaseWeapon.cpp
@@ -121,27 +121,27 @@ void CBaseWeapon::onPostLoad()
 
 	if(m_szSndDraw[0])
 	{
-		m_idSndDraw = SSCore_SndCreate3dInst(m_szSndDraw, false, 0, 100);
+		m_idSndDraw = SSCore_SndCreate3dInst(m_szSndDraw, SX_SOUND_CHANNEL_GAME, 100);
 	}
 	if(m_szSndHolster[0])
 	{
-		m_idSndHolster = SSCore_SndCreate3dInst(m_szSndHolster, false, 0, 100);
+		m_idSndHolster = SSCore_SndCreate3dInst(m_szSndHolster, SX_SOUND_CHANNEL_GAME, 100);
 	}
 	if(m_szSndShoot[0])
 	{
-		m_idSndShoot = SSCore_SndCreate3dInst(m_szSndShoot, false, 0, 100);
+		m_idSndShoot = SSCore_SndCreate3dInst(m_szSndShoot, SX_SOUND_CHANNEL_GAME, 100);
 	}
 	if(m_szSndEmpty[0])
 	{
-		m_idSndEmpty = SSCore_SndCreate3dInst(m_szSndEmpty, false, 0, 100);
+		m_idSndEmpty = SSCore_SndCreate3dInst(m_szSndEmpty, SX_SOUND_CHANNEL_GAME, 100);
 	}
 	if(m_szSndReload[0])
 	{
-		m_idSndReload = SSCore_SndCreate3dInst(m_szSndReload, false, 0, 100);
+		m_idSndReload = SSCore_SndCreate3dInst(m_szSndReload, SX_SOUND_CHANNEL_GAME, 100);
 	}
 	if(m_szSndSwitch[0])
 	{
-		m_idSndSwitch = SSCore_SndCreate3dInst(m_szSndSwitch, false, 0, 100);
+		m_idSndSwitch = SSCore_SndCreate3dInst(m_szSndSwitch, SX_SOUND_CHANNEL_GAME, 100);
 	}
 }
 
@@ -199,7 +199,7 @@ void CBaseWeapon::primaryAction(BOOL st)
 		}
 		if(ID_VALID(m_iSoundAction1))
 		{
-			SSCore_SndInstancePlay3d(m_iSoundAction1, &getPos());
+			SSCore_SndInstancePlay3d(m_iSoundAction1, false, false, &getPos());
 		}
 
 		//((CPlayer*)m_pOwner)->is
@@ -258,7 +258,7 @@ void CBaseWeapon::reload()
 		playAnimation("reload");
 		if(ID_VALID(m_idSndReload))
 		{
-			SSCore_SndInstancePlay3d(m_idSndReload, &getPos());
+			SSCore_SndInstancePlay3d(m_idSndReload, false, false, &getPos());
 		}
 	}
 }
@@ -270,7 +270,7 @@ void CBaseWeapon::setFireMode(FIRE_MODE mode)
 		m_fireMode = mode;
 		if(ID_VALID(m_idSndReload))
 		{
-			SSCore_SndInstancePlay3d(m_idSndSwitch, &getPos());
+			SSCore_SndInstancePlay3d(m_idSndSwitch, false, false, &getPos());
 		}
 	}
 }
diff --git a/source/game/GameData.cpp b/source/game/GameData.cpp
index 7e8544891f1d71cbbf23a70cba63e1f960c444fd..278467beb049fb12996f4b18b3d7cb4bd5e0936c 100644
--- a/source/game/GameData.cpp
+++ b/source/game/GameData.cpp
@@ -126,7 +126,7 @@ void GameData::playFootstepSound(MTLTYPE_PHYSIC mtl_type, const float3 &f3Pos)
 		return;
 	}
 	ID idSound = m_pidFootstepSound[mtl_type][rand() % iCount];
-	SSCore_SndInstancePlay3d(idSound, (float3*)&f3Pos);
+	SSCore_SndInstancePlay3d(idSound, false, false, (float3*)&f3Pos);
 }
 
 void GameData::loadFoostepsSounds()
@@ -173,7 +173,7 @@ void GameData::loadFoostepsSounds()
 		m_pidFootstepSound[i] = jl ? new ID[jl] : NULL;
 		for(int j = 0; j < jl; ++j)
 		{
-			m_pidFootstepSound[i][j] = SSCore_SndCreate3dInst(paSounds[0][j], false, 0, 100);
+			m_pidFootstepSound[i][j] = SSCore_SndCreate3dInst(paSounds[0][j], SX_SOUND_CHANNEL_GAME, 100);
 		}
 	}
 }
diff --git a/source/game/NPCZombie.cpp b/source/game/NPCZombie.cpp
index d4ccd413c81c8caca46baf5b58b87017f1089302..e9e647b0e4ab9e989c328f220b64425a6a9c3f9d 100644
--- a/source/game/NPCZombie.cpp
+++ b/source/game/NPCZombie.cpp
@@ -24,9 +24,9 @@ CNPCZombie::CNPCZombie(CEntityManager * pMgr) :
 	m_fSpeedWalk = 0.07f;
 	m_fSpeedRun = 0.12f;
 
-	m_idSndIdle = SSCore_SndCreate3d("mobs/zombie/zombie_idle_16.ogg", false, 0, 30);
-	m_idSndIdle2 = SSCore_SndCreate3d("mobs/zombie/zombie_idle_17.ogg", false, 0, 30);
-	m_idSndDeath = SSCore_SndCreate3d("mobs/zombie/zombie_die_1.ogg", false, 0, 45);
+	m_idSndIdle = SSCore_SndCreate3d("mobs/zombie/zombie_idle_16.ogg", SX_SOUND_CHANNEL_GAME, 0, 30);
+	m_idSndIdle2 = SSCore_SndCreate3d("mobs/zombie/zombie_idle_17.ogg", SX_SOUND_CHANNEL_GAME, 0, 30);
+	m_idSndDeath = SSCore_SndCreate3d("mobs/zombie/zombie_die_1.ogg", SX_SOUND_CHANNEL_GAME, 0, 45);
 }
 
 CNPCZombie::~CNPCZombie()
@@ -38,9 +38,9 @@ void CNPCZombie::onSync()
 {
 	BaseClass::onSync();
 
-	SSCore_SndPosWSet(m_idSndIdle, &getPos());
-	SSCore_SndPosWSet(m_idSndIdle2, &getPos());
-	SSCore_SndPosWSet(m_idSndDeath, &getPos());
+	SSCore_SndSetPosWorld(m_idSndIdle, &getPos());
+	SSCore_SndSetPosWorld(m_idSndIdle2, &getPos());
+	SSCore_SndSetPosWorld(m_idSndDeath, &getPos());
 
 	//если здоровье меньше нуля
 	if (m_fHealth < 0.0f)
diff --git a/source/gcore/shader.cpp b/source/gcore/shader.cpp
index e81b4e176584bb24b3b2a0db013b266ad4c7c9ab..2de55a6e47aa6a1dbd925c2a15b08685a631f9f2 100644
--- a/source/gcore/shader.cpp
+++ b/source/gcore/shader.cpp
@@ -616,6 +616,7 @@ void CShaderManager::allLoad()
 	if (m_aVS.size() == m_iLastAllLoadVS || m_aPS.size() == m_iLastAllLoadPS)
 		return;
 
+	DWORD dwTime = GetTickCount();
 	LibReport(REPORT_MSG_LEVEL_NOTICE, "load shaders ...\n");
 	
 	for (int i = 0, il = m_aVS.size(); i < il; ++i)
@@ -639,7 +640,7 @@ void CShaderManager::allLoad()
 	m_iLastAllLoadVS = m_aVS.size();
 	m_iLastAllLoadPS = m_aPS.size();
 
-	LibReport(REPORT_MSG_LEVEL_NOTICE, "all loaded shaders\n");
+	LibReport(REPORT_MSG_LEVEL_NOTICE, "all loaded shaders, time %d\n", GetTickCount() - dwTime);
 }
 
 void CShaderManager::update(SHADER_TYPE type_shader, const char *szName)
diff --git a/source/gcore/sxgcore.cpp b/source/gcore/sxgcore.cpp
index 6905957b693718b6a79b03aa8f86a5afef227317..01ed825cc6c21edbc6be29c7f49b33b52b5cdd58 100644
--- a/source/gcore/sxgcore.cpp
+++ b/source/gcore/sxgcore.cpp
@@ -457,7 +457,7 @@ SX_LIB_API ID SGCore_ShaderLoad(SHADER_TYPE type_shader, const char *szPath, con
 
 SX_LIB_API void SGCore_ShaderAllLoad()
 {
-	SG_PRECOND();
+	SG_PRECOND(_VOID);
 
 	return g_pManagerShaders->allLoad();
 }
diff --git a/source/gdefines.h b/source/gdefines.h
index f5c235178c384eaa4b6c2845eea9adffeec854a8..a49977adf08e37e81ac0fa75f5f7c1b95ddcd122 100644
--- a/source/gdefines.h
+++ b/source/gdefines.h
@@ -103,6 +103,12 @@ struct IBaseObject
 #define CONFIG_SECTION_MAX_LEN	64	/*!< максимальная длина секции конфигурационного файла */
 //!@}
 
+/*! звуковой канал самой игры */
+#define SX_SOUND_CHANNEL_GAME	0
+
+/*! звуковой канал главного меню */
+#define SX_SOUND_CHANNEL_MAIN_MENU	1
+
 /*! Пустые дефайны для визуальной идентификации аргументов функций
 @{
 */
diff --git a/source/geom/green.cpp b/source/geom/green.cpp
index ddf5720563f72f2e6ffc3ca1d7723cb9619045e7..5df2543a36e657a6ea100c0e2da3ee28740335ca 100644
--- a/source/geom/green.cpp
+++ b/source/geom/green.cpp
@@ -1871,7 +1871,6 @@ bool CGreen::traceBeam(const float3* start, const float3* dir, float3* _res, ID*
 		return false;
 
 	SXTriangle tmptri;
-	float dist;
 	bool tmpiscom = true;
 	float3 ip;
 	float3 res;
@@ -1955,7 +1954,6 @@ bool CGreen::traceBeam(const float3* start, const float3* dir, float3* _res, ID*
 void CGreen::getPartBB(float3* bbmin, float3 * bbmax, CSegment** arrsplits, int *count, CSegment* comsegment, ID curr_splits_ids_render)
 {
 	float3 min,max;
-	float radius;
 	comsegment->m_pBoundVolumeP->getMinMax(&min, &max);
 
 	if (comsegment->m_iCountObj > 0 && SGCore_0InretsectBox(bbmin, bbmax, &min, &max))
diff --git a/source/geom/static_geom.cpp b/source/geom/static_geom.cpp
index 42b1ee3d74c7dab91c64a2bc8185ff7f3b7f8bbe..3f69191926a9744e3974c29a98b9315b2d83dc7c 100644
--- a/source/geom/static_geom.cpp
+++ b/source/geom/static_geom.cpp
@@ -2959,7 +2959,6 @@ void CStaticGeom::applyTransform(ID id)
 	applyTransformLod(id);
 
 	vertex_static* pData;
-	float3_t* pData2;
 	int idgroup;
 	int idbuff;
 
@@ -3298,7 +3297,6 @@ bool CStaticGeom::traceBeam(const float3* start, const float3* dir, float3* _res
 		return false;
 
 	SXTriangle tmptri;
-	float dist;
 	bool tmpiscom = true;
 	float3 ip;
 	float3 res;
diff --git a/source/level/AmbientSounds.cpp b/source/level/AmbientSounds.cpp
index 3932a81b637e77bec9283218279e6d921a5acabe..055437021daba20be5b4c0da767cf9877da4e05a 100644
--- a/source/level/AmbientSounds.cpp
+++ b/source/level/AmbientSounds.cpp
@@ -19,7 +19,7 @@ CAmbientSounds::~CAmbientSounds()
 
 void CAmbientSounds::add(const char *szPath)
 {
-	ID id = SSCore_SndCreate2d(szPath);
+	ID id = SSCore_SndCreate2d(szPath, SX_SOUND_CHANNEL_GAME);
 	if (id >= 0)
 		m_aIDSnds.push_back(id);
 }
@@ -28,7 +28,7 @@ void CAmbientSounds::get(ID id, char *szPath)
 {
 	if (id >= 0 && id < m_aIDSnds.size())
 	{
-		SSCore_SndFileGet(m_aIDSnds[id], szPath);
+		SSCore_SndGetFile(m_aIDSnds[id], szPath);
 	}
 }
 
@@ -51,7 +51,7 @@ void CAmbientSounds::play()
 {
 	if (m_iPlayingLast >= 0 && m_iPlayingLast < m_aIDSnds.size())
 	{
-		SSCore_SndVolumeSet(m_aIDSnds[m_iPlayingLast], 100);
+		SSCore_SndSetVolume(m_aIDSnds[m_iPlayingLast], 100);
 		SSCore_SndPlay(m_aIDSnds[m_iPlayingLast]);
 		m_isPlaying = true;
 	}
@@ -65,14 +65,14 @@ void CAmbientSounds::update()
 	static const float * env_ambient_snd_volume = GET_PCVAR_FLOAT("env_ambient_snd_volume");
 	static float env_ambient_snd_volume_old = 1.f;
 
-	if (SSCore_SndStateGet(m_aIDSnds[m_iPlayingLast]) != SOUND_OBJSTATE_PLAY)
+	if (SSCore_SndGetState(m_aIDSnds[m_iPlayingLast]) != SOUND_OBJSTATE_PLAY)
 	{
 		if (m_iPlayingLast + 1 < m_aIDSnds.size())
 			++m_iPlayingLast;
 		else
 			m_iPlayingLast = 0;
 
-		SSCore_SndVolumeSet(m_aIDSnds[m_iPlayingLast], env_ambient_snd_volume_old*100.f);
+		SSCore_SndSetVolume(m_aIDSnds[m_iPlayingLast], env_ambient_snd_volume_old*100.f);
 		SSCore_SndPlay(m_aIDSnds[m_iPlayingLast]);
 	}
 
@@ -80,7 +80,7 @@ void CAmbientSounds::update()
 	{
 		env_ambient_snd_volume_old = *env_ambient_snd_volume;
 		if (m_iPlayingLast >= 0)
-			SSCore_SndVolumeSet(m_aIDSnds[m_iPlayingLast], env_ambient_snd_volume_old*100.f);
+			SSCore_SndSetVolume(m_aIDSnds[m_iPlayingLast], env_ambient_snd_volume_old*100.f);
 	}
 }
 
diff --git a/source/level/weather.cpp b/source/level/weather.cpp
index 85bd30871b6469a51c7b4ec7aa06a8dec843e92a..5fb9ccb16dc1c8e4156fad25e136dfa775c29d8f 100644
--- a/source/level/weather.cpp
+++ b/source/level/weather.cpp
@@ -77,7 +77,7 @@ void CWeatherRndSnd::addSound(const char *szPath)
 
 	if (isunic)
 	{
-		ID tmpid = SSCore_SndCreate2d(szPath);
+		ID tmpid = SSCore_SndCreate2d(szPath, SX_SOUND_CHANNEL_GAME);
 		m_aArrSnds.push_back(CSnd(szPath, tmpid));
 		m_aCurrSndIDs.push_back(tmpid);
 	}
@@ -100,13 +100,13 @@ void CWeatherRndSnd::update()
 		if((int)m_aCurrSndIDs.size() > tmpkeysnd && m_aCurrSndIDs[tmpkeysnd] && m_aCurrSndIDs[tmpkeysnd] >= 0)
 		{
 			m_idCurrPlay = m_aCurrSndIDs[tmpkeysnd];
-			SSCore_SndPosCurrSet(m_idCurrPlay, 0);
+			SSCore_SndSetPosPlay(m_idCurrPlay, 0);
 			int tmprndvol = (rand() % (m_iVolumeE - m_iVolumeB)) + m_iVolumeB;
-			SSCore_SndVolumeSet(m_idCurrPlay, (long)(env_weather_snd_volume ? (float)tmprndvol * (*env_weather_snd_volume) : tmprndvol), SOUND_VOL_PCT);
+			SSCore_SndSetVolume(m_idCurrPlay, ((float)(env_weather_snd_volume ? (float)tmprndvol * (*env_weather_snd_volume) : tmprndvol))*0.01f);
 			SSCore_SndPlay(m_idCurrPlay);
 
 			DWORD tmprnd = (rand() % (m_ulPeriodE - m_ulPeriodB)) + m_ulPeriodB;
-			m_ulNextPlay = TimeGetMls(Core_RIntGet(G_RI_INT_TIMER_RENDER)) + tmprnd + ((SSCore_SndLengthSecGet(m_idCurrPlay) + 1) * 1000);
+			m_ulNextPlay = TimeGetMls(Core_RIntGet(G_RI_INT_TIMER_RENDER)) + tmprnd + ((SSCore_SndGetLengthSec(m_idCurrPlay) + 1) * 1000);
 		}
 	}
 }
@@ -118,7 +118,7 @@ void CWeatherRndSnd::play()
 
 	m_isPlaying = true;
 
-	if (m_idCurrPlay >= 0 && SSCore_SndStateGet(m_idCurrPlay) == SOUND_OBJSTATE_PAUSE)
+	if (m_idCurrPlay >= 0 && SSCore_SndGetState(m_idCurrPlay) == SOUND_OBJSTATE_PAUSE)
 		SSCore_SndPlay(m_idCurrPlay);
 }
 
@@ -129,7 +129,7 @@ void CWeatherRndSnd::pause()
 
 	m_isPlaying = false;
 
-	if (m_idCurrPlay >= 0 && SSCore_SndStateGet(m_idCurrPlay) == SOUND_OBJSTATE_PLAY)
+	if (m_idCurrPlay >= 0 && SSCore_SndGetState(m_idCurrPlay) == SOUND_OBJSTATE_PLAY)
 		SSCore_SndPlay(SOUND_OBJSTATE_PAUSE);
 }
 
@@ -176,8 +176,8 @@ CWeather::CWeather()
 
 	m_idLightThunderbolt = SML_LigthsCreatePoint(&float3(0, 0, 0), 200, &float3(1, 1, 1), false, true);
 	SML_LigthsSetEnable(m_idLightThunderbolt, false);
-	m_idSndRain = SSCore_SndCreate2d("nature/rain.ogg",true);
-	m_idSndThunder = SSCore_SndCreate2d("nature/thunder.ogg");
+	m_idSndRain = SSCore_SndCreate2d("nature/rain.ogg", SX_SOUND_CHANNEL_GAME, true);
+	m_idSndThunder = SSCore_SndCreate2d("nature/thunder.ogg", SX_SOUND_CHANNEL_GAME);
 
 	m_fRainVolume = 0;
 }
@@ -646,8 +646,8 @@ void CWeather::update()
 			SPE_EmitterSet(m_idEffRain, 0, ReCreateCount, env_default_rain_density_old * m_aTimeSections[m_iSectionCurr].m_DataSection.m_fRainDensity * float(WEATHER_RAIN_RECREATE_COUNT));
 			SPE_EffectEnableSet(m_idEffRain, true);
 
-			SSCore_SndPosCurrSet(m_idSndRain, 0);
-			SSCore_SndVolumeSet(m_idSndRain, 0, SOUND_VOL_PCT);
+			SSCore_SndSetPosPlay(m_idSndRain, 0);
+			SSCore_SndSetVolume(m_idSndRain, 0);
 
 			if (m_isPlaying)
 				SSCore_SndPlay(m_idSndRain);
@@ -780,8 +780,8 @@ void CWeather::update()
 			}
 			else
 			{
-				SSCore_SndPosCurrSet(m_idSndThunder, 0);
-				SSCore_SndVolumeSet(m_idSndThunder, (env_weather_snd_volume ? (*env_weather_snd_volume) : 1.f) * 100.f, SOUND_VOL_PCT);
+				SSCore_SndSetPosPlay(m_idSndThunder, 0);
+				SSCore_SndSetVolume(m_idSndThunder, (env_weather_snd_volume ? (*env_weather_snd_volume) : 1.f));
 
 				if (m_isPlaying)
 					SSCore_SndPlay(m_idSndThunder);
@@ -806,8 +806,8 @@ void CWeather::update()
 			SML_LigthsSetEnable(m_idLightThunderbolt, false);
 
 			//и заодно проиграть звук молнии
-			SSCore_SndPosCurrSet(m_idSndThunder, 0);
-			SSCore_SndVolumeSet(m_idSndThunder, clampf(m_fRainVolume*2.f*100.f,0.f,100.f), SOUND_VOL_PCT);
+			SSCore_SndSetPosPlay(m_idSndThunder, 0);
+			SSCore_SndSetVolume(m_idSndThunder, clampf(m_fRainVolume*2.f, 0.f, 1.f));
 			
 			if (m_isPlaying)
 				SSCore_SndPlay(m_idSndThunder);
@@ -859,7 +859,7 @@ void CWeather::updateRainSound()
 	}
 
 	m_fRainVolume /= tmpcount / 4;
-	SSCore_SndVolumeSet(m_idSndRain, (env_weather_snd_volume ? (*env_weather_snd_volume) : 1.f) *  m_fRainVolume * 100.f, SOUND_VOL_PCT);
+	SSCore_SndSetVolume(m_idSndRain, (env_weather_snd_volume ? (*env_weather_snd_volume) : 1.f) *  m_fRainVolume);
 }
 
 float CWeather::getCurrRainDensity()
@@ -878,10 +878,10 @@ void CWeather::sndPlay()
 	m_isPlaying = true;
 	m_RndSnd.play();
 
-	if (m_idSndRain >= 0 && SSCore_SndStateGet(m_idSndRain) == SOUND_OBJSTATE_PAUSE)
+	if (m_idSndRain >= 0 && SSCore_SndGetState(m_idSndRain) == SOUND_OBJSTATE_PAUSE)
 		SSCore_SndPlay(m_idSndRain);
 
-	if (m_idSndThunder >= 0 && SSCore_SndStateGet(m_idSndThunder) == SOUND_OBJSTATE_PAUSE)
+	if (m_idSndThunder >= 0 && SSCore_SndGetState(m_idSndThunder) == SOUND_OBJSTATE_PAUSE)
 		SSCore_SndPlay(m_idSndThunder);
 }
 
@@ -893,10 +893,10 @@ void CWeather::sndPause()
 	m_isPlaying = false;
 	m_RndSnd.pause();
 
-	if (m_idSndRain >= 0 && SSCore_SndStateGet(m_idSndRain) == SOUND_OBJSTATE_PLAY)
+	if (m_idSndRain >= 0 && SSCore_SndGetState(m_idSndRain) == SOUND_OBJSTATE_PLAY)
 		SSCore_SndPause(m_idSndRain);
 
-	if (m_idSndThunder >= 0 && SSCore_SndStateGet(m_idSndThunder) == SOUND_OBJSTATE_PLAY)
+	if (m_idSndThunder >= 0 && SSCore_SndGetState(m_idSndThunder) == SOUND_OBJSTATE_PLAY)
 		SSCore_SndPause(m_idSndThunder);
 }
 
diff --git a/source/mtllight/light.cpp b/source/mtllight/light.cpp
index 74b59a158471d51923b2e5c3caab522410921c91..8ea957c2a80dd6fe5882dccbc9aea8d0df873397 100644
--- a/source/mtllight/light.cpp
+++ b/source/mtllight/light.cpp
@@ -265,7 +265,7 @@ bool Lights::getExists(ID id) const
 
 void Lights::DeleteLight(ID id)
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 	if (ArrLights[id]->IsGlobal)
 		GlobalLight = -1;
@@ -285,7 +285,7 @@ char* Lights::GetLightName(ID id)
 
 void Lights::SetLightName(ID id, const char* name)
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 	sprintf(ArrLights[id]->Name, "%s", name);
 }
 
@@ -443,7 +443,7 @@ ID Lights::CreateDirection(ID id, const float3* pos, float dist, const float3* c
 
 void Lights::Render(ID id, DWORD timeDelta)
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 	float4x4 tmpwmat = ArrLights[id]->WorldMat;
 	MLSet::DXDevice->SetTransform(D3DTS_WORLD, &(ArrLights[id]->WorldMat.operator D3DXMATRIX()));
@@ -468,21 +468,21 @@ void Lights::SetCastGlobalShadow(bool isShadowed)
 
 void Lights::GetLightColor(ID id, float3* vec) const
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 	(*vec) = ArrLights[id]->Color;
 }
 
 void Lights::SetLightColor(ID id, const float3* vec)
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 	ArrLights[id]->Color = *vec;
 }
 
 void Lights::GetLightPos(ID id, float3* vec, bool greal) const
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 	if (ArrLights[id]->IsGlobal && !greal)
 	{
@@ -527,7 +527,7 @@ float Lights::GetLightDist(ID id) const
 
 void Lights::SetLightDist(ID id, float radius_height, bool is_create)
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 	ArrLights[id]->Dist = radius_height;
 	if (ArrLights[id]->TypeLight == LTYPE_LIGHT_DIR && is_create)
@@ -562,7 +562,7 @@ void Lights::SetLightDist(ID id, float radius_height, bool is_create)
 
 void Lights::SetLightPos(ID id, const float3* vec, bool greal)
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 	if (ArrLights[id]->IsGlobal)
 	{
@@ -615,14 +615,14 @@ void Lights::SetLightPos(ID id, const float3* vec, bool greal)
 
 void Lights::GetLightOrient(ID id, SMQuaternion* q) const
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 	*q = ArrLights[id]->Quaternion;
 }
 
 void Lights::SetLightOrient(ID id, const SMQuaternion* q)
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 	ArrLights[id]->Quaternion = *q;
 
@@ -634,7 +634,7 @@ void Lights::SetLightOrient(ID id, const SMQuaternion* q)
 
 void Lights::SetShadowBias(ID id, float val)
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 		if (ArrLights[id]->ShadowSM)
 			ArrLights[id]->ShadowSM->SetBias(val);
@@ -733,7 +733,7 @@ bool Lights::GetLightEnable(ID id) const
 
 void Lights::SetLightEnable(ID id, bool val)
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 	ArrLights[id]->IsEnable = val;
 	LightCountUpdateNull(id);
@@ -754,7 +754,7 @@ LTYPE_LIGHT Lights::GetLightType(ID id) const
 
 void Lights::ShadowRenderBegin(ID id)
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 	if (ArrLights[id]->ShadowSM)
 		ArrLights[id]->ShadowSM->Begin();
@@ -766,7 +766,7 @@ void Lights::ShadowRenderBegin(ID id)
 
 void Lights::ShadowRenderEnd(ID id)
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 	if (ArrLights[id]->ShadowSM)
 		ArrLights[id]->ShadowSM->End();
@@ -778,7 +778,7 @@ void Lights::ShadowRenderEnd(ID id)
 
 void Lights::ShadowRenderPre(ID id, int cube)
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 	if (ArrLights[id]->ShadowCube)
 		ArrLights[id]->ShadowCube->Pre(cube);
@@ -788,7 +788,7 @@ void Lights::ShadowRenderPre(ID id, int cube)
 
 void Lights::ShadowRenderPost(ID id, int cube)
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 	if (ArrLights[id]->ShadowCube)
 		ArrLights[id]->ShadowCube->Post(cube);
@@ -900,14 +900,14 @@ ISXFrustum* Lights::GetLightFrustumG(ID id, int split) const
 
 void Lights::UpdateLightGFrustums(ID id, int split, const float3* pos, const float3* dir)
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 	ArrLights[id]->ShadowPSSM->UpdateFrustums(split, pos, dir);
 }
 
 void Lights::ShadowGen2(ID id)
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 	if (ArrLights[id]->ShadowSM)
 		ArrLights[id]->ShadowSM->GenShadow2(SGCore_RTGetTexture(ShadowMap));
@@ -945,7 +945,7 @@ void Lights::ShadowNull()
 
 void Lights::SetLightAngle(ID id, float angle, bool is_create)
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 		ArrLights[id]->Angle = angle;
 		if (ArrLights[id]->TypeLight == LTYPE_LIGHT_DIR && is_create)
@@ -972,7 +972,7 @@ void Lights::SetLightAngle(ID id, float angle, bool is_create)
 
 void Lights::SetLightTopRadius(ID id, float top_radius)
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 		if (ArrLights[id]->TypeLight == 1)
 		{
@@ -994,7 +994,7 @@ void Lights::SetLightTopRadius(ID id, float top_radius)
 
 void Lights::SetShadowBlurPixel(ID id, float blur_pixel)
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 		if (ArrLights[id]->ShadowCube)
 			ArrLights[id]->ShadowCube->SetBlurPixel(blur_pixel);
@@ -1021,7 +1021,7 @@ float Lights::GetShadowBlurPixel(ID id) const
 
 void Lights::SetShadowLocalNear(ID id, float slnear)
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 	if (ArrLights[id]->ShadowCube)
 		ArrLights[id]->ShadowCube->SetNear(slnear);
@@ -1044,7 +1044,7 @@ float Lights::GetShadowLocalNear(ID id) const
 
 void Lights::SetShadowLocalFar(ID id, float slfar)
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 	if (ArrLights[id]->ShadowCube)
 	{
@@ -1077,7 +1077,7 @@ float Lights::GetShadowLocalFar(ID id) const
 
 void Lights::SetLightCubeEdgeEnable(ID id, int edge, bool enable)
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 	if (ArrLights[id]->ShadowCube)
 		ArrLights[id]->ShadowCube->SetEnableCubeEdge(edge, enable);
@@ -1118,7 +1118,7 @@ ID Lights::GetLightIDArr(ID id, ID inid, int how)
 
 void Lights::SetLightIDArr(ID id, ID inid, int how, ID id_arr)
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 		if (ArrLights[id]->ShadowSM)
 		{
@@ -1139,7 +1139,7 @@ void Lights::SetLightIDArr(ID id, ID inid, int how, ID id_arr)
 
 void Lights::SetLightTypeShadowed(ID id, LTYPE_SHADOW type)
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 	ArrLights[id]->TypeShadowed = type;
 
@@ -1490,7 +1490,7 @@ void Lights::ToneMappingCom(DWORD timeDelta, float factor_adapted)
 
 void Lights::Set4Or3Splits(ID id, bool is4)
 {
-	LIGHTS_PRE_COND_ID(id);
+	LIGHTS_PRE_COND_ID(id, _VOID);
 
 	if (ArrLights[id]->ShadowPSSM)
 		ArrLights[id]->ShadowPSSM->Set4Or3Splits(is4);
@@ -1521,7 +1521,7 @@ LTYPE_LIGHT Lights::DelGetType(ID key)
 
 void Lights::DelDel(ID key)
 {
-	LIGHTS_PRE_COND_KEY_DEL(key);
+	LIGHTS_PRE_COND_KEY_DEL(key, _VOID);
 	mem_delete(ArrDelLights[key]);
 	ArrDelLights.erase(key);
 }
diff --git a/source/mtllight/material.cpp b/source/mtllight/material.cpp
index 22b28f6daadf2065374ce70b9eb31fe033ae46cf..3a0b2ad9110f6d78c23cd9d51399c874f9378457 100644
--- a/source/mtllight/material.cpp
+++ b/source/mtllight/material.cpp
@@ -143,9 +143,9 @@ Materials::Material::Material()
 
 	Type = MTLTYPE_MODEL_STATIC;
 
-	MainTexture - 1;
-	PreShaderVS - 1;
-	PreShaderPS - 1;
+	MainTexture = -1;
+	PreShaderVS = -1;
+	PreShaderPS = -1;
 }
 
 void Materials::Material::Nulling()
@@ -160,9 +160,9 @@ void Materials::Material::Nulling()
 
 	Type = MTLTYPE_MODEL_STATIC;
 
-	MainTexture-1;
-	PreShaderVS-1;
-	PreShaderPS-1;
+	MainTexture = -1;
+	PreShaderVS = -1;
+	PreShaderPS = -1;
 	
 	MicroDetail = MaterialMaskPM();
 	LightParam = MaterialLightParam();
@@ -399,7 +399,7 @@ MTLTYPE_MODEL Materials::GetTypeModel(ID id)
 
 void Materials::SetTypeModel(ID id, MTLTYPE_MODEL type_model)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->mtl->Type = type_model;
 }
 
@@ -411,7 +411,7 @@ bool Materials::MtlGetUsingAlphaTest(ID id)
 
 void Materials::MtlSetUsingAlphaTest(ID id, bool is_using)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->mtl->IsAlphaTest = is_using;
 }
 
@@ -426,7 +426,7 @@ MTLTYPE_REFLECT Materials::MtlTypeReflection(ID id)
 
 void Materials::MtlRefSetIDArr(ID id, ID inid, int cube, ID idarr)
 {
-	MTL_REF_PRE_COND_ID(id);
+	MTL_REF_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->Reflect->SetIDArr(inid, cube, idarr);
 }
 
@@ -450,13 +450,13 @@ ID Materials::MtlRefGetIDArr(ID id, ID inid, int cube)
 
 void Materials::MtlRefPreRenderPlane(ID id, D3DXPLANE* plane)
 {
-	MTL_REF_PRE_COND_ID(id);
+	MTL_REF_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->Reflect->PreRenderRefPlane(plane);
 }
 
 ISXFrustum* Materials::MtlRefGetfrustum(ID id, int cube)
 {
-	MTL_REF_PRE_COND_ID(id,0);
+	MTL_REF_PRE_COND_ID(id, 0);
 	if (cube == 0 || (cube > 0 && (ArrMaterials[id]->Reflect->GetTypeReflect() == MTLTYPE_REFLECT_CUBE_STATIC || ArrMaterials[id]->Reflect->GetTypeReflect() == MTLTYPE_REFLECT_CUBE_DYNAMIC)))
 		return ArrMaterials[id]->Reflect->ReflectFrustum[cube];
 	return 0;
@@ -464,26 +464,26 @@ ISXFrustum* Materials::MtlRefGetfrustum(ID id, int cube)
 
 void Materials::MtlRefPostRenderPlane(ID id)
 {
-	MTL_REF_PRE_COND_ID(id);
+	MTL_REF_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->Reflect->PostRenderRefPlane();
 }
 
 IDirect3DTexture9* Materials::MtlRefPlaneGetTex(ID id)
 {
- 	MTL_REF_PRE_COND_ID(id,0);
+ 	MTL_REF_PRE_COND_ID(id, 0);
 	return ArrMaterials[id]->Reflect->GetRefPlaneTex();
 }
 
 
 void Materials::MtlRefSetMinMax(ID id, float3_t* min, float3_t* max)
 {
-	MTL_REF_PRE_COND_ID(id);
+	MTL_REF_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->Reflect->SetMinMax(min,max);
 }
 
 bool Materials::MtlRefIsAllowedRender(ID  id)
 {
-	MTL_REF_PRE_COND_ID(id,false);
+	MTL_REF_PRE_COND_ID(id, false);
 	if (ArrMaterials[id]->Reflect)
 		return ArrMaterials[id]->Reflect->AllowedRender();
 
@@ -493,43 +493,43 @@ bool Materials::MtlRefIsAllowedRender(ID  id)
 
 void Materials::MtlRefCubeBeginRender(ID id, float3_t* center)
 {
-	MTL_REF_PRE_COND_ID(id);
+	MTL_REF_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->Reflect->BeginRenderRefCube(center);
 }
 
 void Materials::MtlRefCubePreRender(ID id, int cube, float4x4* world)
 {
-	MTL_REF_PRE_COND_ID(id);
+	MTL_REF_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->Reflect->PreRenderRefCube(cube, world);
 }
 
 void Materials::MtlRefCubePostRender(ID id, int cube)
 {
-	MTL_REF_PRE_COND_ID(id);
+	MTL_REF_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->Reflect->PostRenderRefCube(cube);
 }
 
 void Materials::MtlRefCubeEndRender(ID id, float3_t* viewpos)
 {
-	MTL_REF_PRE_COND_ID(id);
+	MTL_REF_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->Reflect->EndRenderRefCube(viewpos);
 }
 
 bool Materials::MtlRefUpdateCountUpdate( ID id, float3_t* viewpos)
 {
-	MTL_REF_PRE_COND_ID(id,false);
+	MTL_REF_PRE_COND_ID(id, false);
 	return ArrMaterials[id]->Reflect->UpdateCountUpdate(viewpos);
 }
 
 void Materials::MtlRefNullingCountUpdate(ID id)
 {
-	MTL_REF_PRE_COND_ID(id);
+	MTL_REF_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->Reflect->NullingCountUpdate();
 }
 
 IDirect3DCubeTexture9* Materials::RefCubeGetTex(ID id)
 {
-	MTL_REF_PRE_COND_ID(id,0);
+	MTL_REF_PRE_COND_ID(id, 0);
 	return ArrMaterials[id]->Reflect->GetRefCubeTex();
 }
 
@@ -550,13 +550,13 @@ MTLTYPE_PHYSIC Materials::MtlGetPhysicMaterial(ID id)
 
 void Materials::MtlSetTexture(ID id, const char* path_tex)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->mtl->MainTexture = SGCore_LoadTexAddName(path_tex, LOAD_TEXTURE_TYPE_LOAD);
 }
 
 void Materials::MtlGetTexture(ID id, char* name)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 
 	if (name && ArrMaterials[id]->mtl->MainTexture >= 0)
 		SGCore_LoadTexGetName(ArrMaterials[id]->mtl->MainTexture, name);
@@ -571,25 +571,25 @@ ID Materials::MtlGetTextureID(ID id)
 
 void Materials::MtlSetVS(ID id, const char* path_vs)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->mtl->PreShaderVS = SGCore_ShaderLoad(SHADER_TYPE_VERTEX, path_vs, path_vs, SHADER_CHECKDOUBLE_PATH);
 }
 
 void Materials::MtlGetVS(ID id, char* name)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	SGCore_ShaderGetPath(SHADER_TYPE_VERTEX, ArrMaterials[id]->mtl->PreShaderVS, name);
 }
 
 void Materials::MtlSetPS(ID id, const char* path_ps)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->mtl->PreShaderPS = SGCore_ShaderLoad(SHADER_TYPE_PIXEL, path_ps, path_ps, SHADER_CHECKDOUBLE_PATH);
 }
 
 void Materials::MtlGetPS(ID id, char* name)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	SGCore_ShaderGetPath(SHADER_TYPE_PIXEL, ArrMaterials[id]->mtl->PreShaderPS, name);
 }
 
@@ -598,39 +598,39 @@ void Materials::MtlGetPS(ID id, char* name)
 
 void Materials::MtlSetLighting(ID id, bool is_lighting)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->mtl->IsUnlit = !is_lighting;
 }
 
 bool Materials::MtlGetLighting(ID id)
 {
-	MTL_PRE_COND_ID(id,false);
+	MTL_PRE_COND_ID(id, false);
 	return !ArrMaterials[id]->mtl->IsUnlit;
 }
 
 
 void Materials::MtlSetIsTextureLighting(ID id, bool is_tex_lighting)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->mtl->LightParam.IsTextureParam = is_tex_lighting;
 }
 
 bool Materials::MtlGetIsTextureLighting(ID id)
 {
-	MTL_PRE_COND_ID(id,false);
+	MTL_PRE_COND_ID(id, false);
 	return ArrMaterials[id]->mtl->LightParam.IsTextureParam;
 }
 
 
 void Materials::MtlSetTextureLighting(ID id, const char* path_tex)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->mtl->LightParam.ParamTex = SGCore_LoadTexAddName(path_tex, LOAD_TEXTURE_TYPE_LOAD);
 }
 
 void Materials::MtlGetTextureLighting(ID id, char* path_tex)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	if (path_tex && ArrMaterials[id]->mtl->LightParam.ParamTex >= 0)
 	{
 		SGCore_LoadTexGetName(ArrMaterials[id]->mtl->LightParam.ParamTex, path_tex);
@@ -644,32 +644,32 @@ void Materials::MtlGetTextureLighting(ID id, char* path_tex)
 
 void Materials::MtlSetRoughness(ID id, float roughness)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->mtl->LightParam.RoughnessValue = roughness;
 }
 
 float Materials::MtlGetRoughness(ID id)
 {
-	MTL_PRE_COND_ID(id,-1);
+	MTL_PRE_COND_ID(id, -1);
 	return ArrMaterials[id]->mtl->LightParam.RoughnessValue;
 }
 
 
 void Materials::MtlSetF0(ID id, float f0)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->mtl->LightParam.F0Value = f0;
 }
 
 float Materials::MtlGetF0(ID id)
 {
-	MTL_PRE_COND_ID(id,-1);
+	MTL_PRE_COND_ID(id, -1);
 	return ArrMaterials[id]->mtl->LightParam.F0Value;
 }
 
 void Materials::MtlSetThickness(ID id, float thickness)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->mtl->LightParam.ThicknessValue = thickness;
 }
 
@@ -721,7 +721,7 @@ float Materials::MtlGetDensity(ID id)
 
 void Materials::MtlSetTypeTransparency(ID id, MTLTYPE_TRANSPARENCY type)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->mtl->LightParam.TypeRefraction = type;
 }
 
@@ -734,7 +734,7 @@ MTLTYPE_TRANSPARENCY Materials::MtlGetTypeTransparency(ID id)
 
 void Materials::MtlSetTypeReflection(ID id, MTLTYPE_REFLECT type)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->mtl->LightParam.TypeReflect = type;
 
 	if (ArrMaterials[id]->mtl->LightParam.TypeReflect != MTLTYPE_REFLECT_NONE)
@@ -757,13 +757,13 @@ MTLTYPE_REFLECT Materials::MtlGetTypeReflection(ID id)
 
 void Materials::MtlSetMaskTex(ID id, const char* path_tex)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->mtl->MicroDetail.Mask = SGCore_LoadTexAddName(path_tex, LOAD_TEXTURE_TYPE_LOAD);
 }
 
 void Materials::MtlGetMaskTex(ID id, char* path_tex)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	if (path_tex && ArrMaterials[id]->mtl->MicroDetail.Mask >= 0)
 		SGCore_LoadTexGetName(ArrMaterials[id]->mtl->MicroDetail.Mask, path_tex);
 	else if (path_tex)
@@ -772,13 +772,13 @@ void Materials::MtlGetMaskTex(ID id, char* path_tex)
 
 void Materials::MtlSetMRTex(ID id, int channel, const char* path_tex)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->mtl->MicroDetail.ArrMicroDiffuse[channel] = SGCore_LoadTexAddName(path_tex, LOAD_TEXTURE_TYPE_LOAD);
 }
 
 void Materials::MtlGetMRTex(ID id, int channel, char* path_tex)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	if (path_tex && ArrMaterials[id]->mtl->MicroDetail.ArrMicroDiffuse[channel] >= 0)
 		SGCore_LoadTexGetName(ArrMaterials[id]->mtl->MicroDetail.ArrMicroDiffuse[channel], path_tex);
 	else if (path_tex)
@@ -788,13 +788,13 @@ void Materials::MtlGetMRTex(ID id, int channel, char* path_tex)
 
 void Materials::MtlSetDTex(ID id, int channel, const char* path_tex)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->mtl->MicroDetail.ArrDeatail[channel] = SGCore_LoadTexAddName(path_tex, LOAD_TEXTURE_TYPE_LOAD);
 }
 
 void Materials::MtlGetDTex(ID id, int channel, char* path_tex)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	if (path_tex && ArrMaterials[id]->mtl->MicroDetail.ArrDeatail[channel] >= 0)
 		SGCore_LoadTexGetName(ArrMaterials[id]->mtl->MicroDetail.ArrDeatail[channel], path_tex);
 	else if (path_tex)
@@ -805,7 +805,7 @@ void Materials::MtlGetDTex(ID id, int channel, char* path_tex)
 
 void Materials::MtlSetSTDVS(ID id, MTL_SHADERSTD type, bool is_send)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	if (type == MTL_SHADERSTD_MATRIX_WORLD)
 		ArrMaterials[id]->mtl->VS.IsTransWorld = is_send;
 	else if (type == MTL_SHADERSTD_MATRIX_VIEW)
@@ -831,7 +831,7 @@ void Materials::MtlSetSTDVS(ID id, MTL_SHADERSTD type, bool is_send)
 
 bool Materials::MtlGetSTDVS(ID id, MTL_SHADERSTD type)
 {
-	MTL_PRE_COND_ID(id,false);
+	MTL_PRE_COND_ID(id, false);
 	if (type == MTL_SHADERSTD_MATRIX_WORLD)
 		return ArrMaterials[id]->mtl->VS.IsTransWorld;
 	else if (type == MTL_SHADERSTD_MATRIX_VIEW)
@@ -859,7 +859,7 @@ bool Materials::MtlGetSTDVS(ID id, MTL_SHADERSTD type)
 
 void Materials::MtlSetSTDPS(ID id, MTL_SHADERSTD type, bool is_send)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	if (type == MTL_SHADERSTD_MATRIX_WORLD)
 		ArrMaterials[id]->mtl->PS.IsTransWorld = is_send;
 	else if (type == MTL_SHADERSTD_MATRIX_VIEW)
@@ -885,7 +885,7 @@ void Materials::MtlSetSTDPS(ID id, MTL_SHADERSTD type, bool is_send)
 
 bool Materials::MtlGetSTDPS(ID id, MTL_SHADERSTD type)
 {
-	MTL_PRE_COND_ID(id,false);
+	MTL_PRE_COND_ID(id, false);
 	if (type == MTL_SHADERSTD_MATRIX_WORLD)
 		return ArrMaterials[id]->mtl->PS.IsTransWorld;
 	else if (type == MTL_SHADERSTD_MATRIX_VIEW)
@@ -913,50 +913,50 @@ bool Materials::MtlGetSTDPS(ID id, MTL_SHADERSTD type)
 
 void Materials::MtlSetUDVS(ID id, int component, float val)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->mtl->VS.Param[component] = val;
 }
 
 float Materials::MtlGetUDVS(ID id, int component)
 {
-	MTL_PRE_COND_ID(id,-1);
+	MTL_PRE_COND_ID(id, -1);
 	return ArrMaterials[id]->mtl->VS.Param[component];
 }
 
 void Materials::MtlSetUDVS_InPS(ID id, bool is_send_ps)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->mtl->TransVSDataInPS = is_send_ps;
 }
 
 bool Materials::MtlGetUDVS_InPS(ID id)
 {
-	MTL_PRE_COND_ID(id,false);
+	MTL_PRE_COND_ID(id, false);
 	return ArrMaterials[id]->mtl->TransVSDataInPS;
 }
 
 
 void Materials::MtlSetUDPS(ID id, int component, float val)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->mtl->PS.Param[component] = val;
 }
 
 float Materials::MtlGetUDPS(ID id, int component)
 {
-	MTL_PRE_COND_ID(id,-1);
+	MTL_PRE_COND_ID(id, -1);
 	return ArrMaterials[id]->mtl->PS.Param[component];
 }
 
 void Materials::MtlSetUDPS_InPS(ID id, bool is_send_vs)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 	ArrMaterials[id]->mtl->TransPSDataInVS = is_send_vs;
 }
 
 bool Materials::MtlGetUDPS_InPS(ID id)
 {
-	MTL_PRE_COND_ID(id,false);
+	MTL_PRE_COND_ID(id, false);
 	return ArrMaterials[id]->mtl->TransPSDataInVS;
 }
 
@@ -1104,7 +1104,6 @@ bool Materials::LoadMtl(const char* name, Material** mtl)
 {
 	char* ArrRGBA[4] = { "r", "g", "b", "a" };
 
-	char tmpNameMtl[256];
 	char tmpVS[256];
 	char tmpPS[256];
 
@@ -1603,7 +1602,7 @@ void Materials::MtlReLoad(ID id, const char* name)
 
 void Materials::MtlSave(ID id)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 
 	char tmp_path[256];//папка
 	char tmp_name[256];//само им¤ текстыр с расширением
@@ -1648,9 +1647,6 @@ void Materials::MtlSave(ID id)
 
 	fprintf(file, "[%s]\n", mtrl->Name);
 
-	char tmpPathVS[1024];
-	char tmpPathPS[1024];
-
 	char tmpPathVSName[1024];
 	char tmpPathPSName[1024];
 
@@ -1932,7 +1928,7 @@ void Materials::RenderStd(MTLTYPE_MODEL type, float4x4* world, ID slot, ID id_mt
 
 void Materials::Render(ID id, float4x4* world)
 {
-	MTL_PRE_COND_ID(id);
+	MTL_PRE_COND_ID(id, _VOID);
 
 	static const int *r_win_width = GET_PCVAR_INT("r_win_width");
 	static const int *r_win_height = GET_PCVAR_INT("r_win_height");
@@ -2173,7 +2169,7 @@ void Materials::Render(ID id, float4x4* world)
 
 void Materials::RenderLight(float4_t* color, float4x4* world)
 {
-	MTL_PRE_COND_ID(MtrlDefLight);
+	MTL_PRE_COND_ID(MtrlDefLight, _VOID);
 
 	ArrMaterials[MtrlDefLight]->mtl->PS.Param = *color;
 	Render(MtrlDefLight, world);
diff --git a/source/mtllight/reflection.cpp b/source/mtllight/reflection.cpp
index 71bbbec2f67d6185fd0ac2f4ee5a0f8e30d2c0a4..1001b0bb0c64f9b515f5c043171045bea4fd016f 100644
--- a/source/mtllight/reflection.cpp
+++ b/source/mtllight/reflection.cpp
@@ -291,8 +291,6 @@ void Reflection::PreRenderRefCube(int cube, float4x4* world)
 
 void Reflection::PostRenderRefCube(int cube)
 {
-	LPDIRECT3DSURFACE9 BackBuf;
-
 	mem_release_del(CubeReflectSurface[cube]);
 	mem_release(SurfaceReflect);
 
diff --git a/source/mtllight/sxmtllight.h b/source/mtllight/sxmtllight.h
index ce66190873de830055105e2b184db3e4c1d535cb..dfbb1bb0d4759ed695db764c672b05fc1d1bf5f2 100644
--- a/source/mtllight/sxmtllight.h
+++ b/source/mtllight/sxmtllight.h
@@ -230,7 +230,7 @@ SX_LIB_API void SML_LigthsSetCastGlobalShadow(bool isShadowed);
  \note Предварительный просчет - просчет для всего света (к примеру в другом потоке)
 @{*/
 
-SX_LIB_API bool SML_LigthsComVisibleForFrustum(ID id, const const ISXFrustum *pFrustum);	//!< виден ли свет в данном фрустуме frustum (отдельный просчет)
+SX_LIB_API bool SML_LigthsComVisibleForFrustum(ID id, const ISXFrustum *pFrustum);	//!< виден ли свет в данном фрустуме frustum (отдельный просчет)
 SX_LIB_API float SML_LigthsComDistFor(ID id, const float3 *pViewPos);				//!< дистанция от viewpos до начала света (отдельный просчет)
 
 //! просчет видимости и расстояния от наблюдателя viewpos до начала света, для каждого света (предварительный просчет)
diff --git a/source/pp/sxpp.cpp b/source/pp/sxpp.cpp
index 54a490a6785c84d87ca42248120b783d9c0c8d2d..a45182bed15f025e66528ec9a2ff17dec78b5c24 100644
--- a/source/pp/sxpp.cpp
+++ b/source/pp/sxpp.cpp
@@ -865,12 +865,13 @@ SX_LIB_API void SPP_RenderLensFlare(float3_t* param, float4_t* sun_color, bool u
 	RenderSurf->Release();
 	BackBuf->Release();
 
-	if (GetKeyState('N'))
+	/*if (GetKeyState('N'))
 	{
+		//MessageBox(0,"PP GetKeyState",0,0);
 		char tmppath[1024];
-		sprintf(tmppath, "%sbp.png", "C:\\1\\");
-		D3DXSaveTextureToFile(tmppath, D3DXIFF_PNG, SGCore_RTGetTexture(PPSet::IDsRenderTargets::Bright), NULL);
-	}
+		sprintf(tmppath, "%sbp.jpg", "C:\\1\\");
+		D3DXSaveTextureToFile(tmppath, D3DXIFF_JPG, SGCore_RTGetTexture(PPSet::IDsRenderTargets::Bright), NULL);
+	}*/
 
 
 	SGCore_RTGetTexture(PPSet::IDsRenderTargets::GetSendRT())->GetSurfaceLevel(0, &RenderSurf);
diff --git a/source/render/render_func.cpp b/source/render/render_func.cpp
index f0c3e7936e1afaa861d92e54fc59d8cf4491d9b0..ffb3a8a45693fb8e77bfd059d1cce3d2ea50478c 100644
--- a/source/render/render_func.cpp
+++ b/source/render/render_func.cpp
@@ -216,11 +216,8 @@ void SXRenderFunc::ComVisibleForLight()
 				{
 					for (int k = 0; k < 6; k++)
 					{
-						ID idarr = -1;
-
-						idarr = SGeom_ModelsAddArrForCom();
 						if (SML_LigthsGetIDArr(i, RENDER_IDARRCOM_GEOM, k) <= -1)
-							SML_LigthsSetIDArr(i, RENDER_IDARRCOM_GEOM, k, idarr);
+							SML_LigthsSetIDArr(i, RENDER_IDARRCOM_GEOM, k, SGeom_ModelsAddArrForCom());
 
 						if (SML_LigthsGetIDArr(i, RENDER_IDARRCOM_GREEN, k) <= -1)
 							SML_LigthsSetIDArr(i, RENDER_IDARRCOM_GREEN, k, SGeom_GreenAddArrForCom());
diff --git a/source/score/sound.cpp b/source/score/sound.cpp
index 41b5ce6b54326376347326c1455e16374fc424fd..4f676ad54ae5a7b4d7c2fd9363b63e5b355754d8 100644
--- a/source/score/sound.cpp
+++ b/source/score/sound.cpp
@@ -6,21 +6,22 @@ See the license in LICENSE
 
 #include "sound.h"
 
-size_t ogg_read(void *ptr, size_t size, size_t nmemb, void *datasource)
+//############################################################################
+
+size_t OggCallbackRead(void *ptr, size_t size, size_t nmemb, void *datasource)
 {
 	FILE* f = (FILE*)datasource;
 	return fread(ptr, 1, size * nmemb, f);
 }
 
-int ogg_close(void* datasource)
+int OggCallbackClose(void* datasource)
 {
 	FILE* f = (FILE*)datasource;
 	fclose(f);
 	return 0;
 }
 
-//позиционирование
-int ogg_seek(void *datasource, ogg_int64_t offset, int whence)
+int OggCallbackSeek(void *datasource, ogg_int64_t offset, int whence)
 {
 	FILE* f = (FILE*)datasource;
 	switch (whence)
@@ -33,8 +34,7 @@ int ogg_seek(void *datasource, ogg_int64_t offset, int whence)
 	return 1;
 }
 
-//размер файла
-long ogg_tell(void* datasource)
+long OggCallbackTell(void* datasource)
 {
 	FILE* f = (FILE*)datasource;
 	return ftell(f);
@@ -42,55 +42,442 @@ long ogg_tell(void* datasource)
 
 //############################################################################
 
-MainSound::MainSound()
+CSoundManager::CSoundManager()
 {
-	DeviceSound = 0;
-	DSPrimary = 0;
+	m_pDeviceSound = 0;
+	m_pPrimaryBuffer = 0;
+
+	for (int i = 0; i < SOUND_CHANNELS_COUNT; ++i)
+		m_aChannels[i] = SOUND_CHANNEL_NONE;
 }
 
-MainSound::~MainSound()
+CSoundManager::~CSoundManager()
 {
-	Clear();
-	mem_release_del(DSPrimary);
-	mem_release_del(DeviceSound);
+	clear();
+	mem_release_del(m_pPrimaryBuffer);
+	mem_release_del(m_pDeviceSound);
 }
 
-void MainSound::Clear()
+void CSoundManager::clear()
 {
-	for(UINT i = 0; i < ArrSounds.size(); ++i)
+	for(UINT i = 0; i < m_aSounds.size(); ++i)
 	{
-		mem_delete(ArrSounds[i]);
+		mem_delete(m_aSounds[i]);
 	}
 }
 
-MainSound::Sound::Sound()
+CSoundManager::CSound::CSound()
 {
-	ZeroMemory(this, sizeof(MainSound::Sound));
-	Id = -1;
+	ZeroMemory(this, sizeof(CSoundManager::CSound));
+	m_id = SOUND_FAIL_ID;
+	m_fVolume = 1.f;
 }
 
-MainSound::Sound::~Sound()
+CSoundManager::CSound::~CSound()
 {
-	if (StreamFile)
-		fclose(StreamFile);
+	if (m_pStream)
+		fclose(m_pStream);
 
-	mem_release_del(DSBuffer);
-	if (VorbisFile)
+	//mem_release_del(m_pSoundBuffer);
+	if (m_pVorbisFile)
 	{
-		ov_clear(VorbisFile);
-		mem_delete(VorbisFile);
+		ov_clear(m_pVorbisFile);
+		mem_delete(m_pVorbisFile);
 	}
 }
 
-void MainSound::Init(HWND hwnd)
+//##########################################################################
+
+CSoundManager::СSoundKit::СSoundKit()
+{ 
+	m_szName[0] = 0; 
+	m_idChannel = SOUND_FAIL_ID; 
+	m_is3D = false;
+	m_fDistAudible = SOUND_DIST_AUDIBLE_DEFAULT;
+}
+
+CSoundManager::СSoundKit::~СSoundKit()
+{
+	
+}
+
+ID CSoundManager::sndkitCreate(const char *szName, ID idChannel, bool is3D, float fDistAudible)
+{
+	// список звуков подлежащаих загрузке
+	СSoundKit *pSndKit = new СSoundKit();
+	pSndKit->m_idChannel = idChannel;
+	pSndKit->m_is3D = is3D;
+	pSndKit->m_fDistAudible = fDistAudible;
+	sprintf(pSndKit->m_szName, "%s", szName);
+
+	m_aSoundKits.push_back(pSndKit);
+
+	return m_aSoundKits.size() - 1;
+}
+
+ID CSoundManager::sndkitCreateFromList(const char *szName, ID idChannel, Array<String> aStrings, bool is3D, float fDistAudible, float fVolume)
 {
-	if (FAILED(DirectSoundCreate8(NULL, &DeviceSound, NULL)))
+	СSoundKit *pSndKit = new СSoundKit();
+	pSndKit->m_idChannel = idChannel;
+	pSndKit->m_is3D = is3D;
+	pSndKit->m_fDistAudible = fDistAudible;
+	sprintf(pSndKit->m_szName, "%s", szName);
+	m_aSoundKits.push_back(pSndKit);
+	ID idSndKit = m_aSoundKits.size() - 1;
+
+	String sFileData;
+	float fDistAudibleData = -2.f;
+	float fVolumeData = -2.f;
+	Array<UINT> aDelaysData;
+
+	for (int i = 0, il = aStrings.size(); i < il; ++i)
+	{
+		aDelaysData.clearFast();
+		fDistAudibleData = -2.f;
+		fVolumeData = -2.f;
+
+		if (SndGetDataFromStr(aStrings[i].c_str(), sFileData, fDistAudibleData, fVolumeData, aDelaysData))
+		{
+			if (fDistAudibleData == -2.f)
+				fDistAudibleData = -1.f;
+
+			if (fVolumeData == -2.f)
+				fVolumeData = fVolume;
+
+			sndkitAddSound(idSndKit, sFileData.c_str(), fDistAudibleData, fVolumeData, (aDelaysData.size() > 0 ? &(aDelaysData[0]) : 0), aDelaysData.size());
+		}
+		else
+			sndkitAddSound(idSndKit, StrTrim(aStrings[i].c_str()).c_str(), pSndKit->m_fDistAudible, fVolume);
+	}
+
+	return idSndKit;
+}
+
+void CSoundManager::sndkitAddSound(ID idSndKit, const char *szFile, float fDistAudible, float fVolume, UINT *pArrDelay, int iSizeArrDelay)
+{
+	SOUND_SNDKIT_PRECOND(idSndKit, _VOID);
+
+	СSoundKit *pSndKit = m_aSoundKits[idSndKit];
+
+	ID idSnd = SOUND_FAIL_ID;
+
+	if (pSndKit->m_is3D)
+		idSnd = soundCreate3dInst(szFile, pSndKit->m_idChannel, (fDistAudible > 0 ? fDistAudible : pSndKit->m_fDistAudible));
+	else
+		idSnd = soundCreate2dInst(szFile, pSndKit->m_idChannel);
+
+	СSoundKit::CSoundKitObject oSndKitObj;
+	oSndKitObj.m_id = idSnd;
+	oSndKitObj.m_fVolume = fVolume;
+
+	for (int i = 0, il = iSizeArrDelay; i < il; ++i)
+	{
+		oSndKitObj.m_aDelays.push_back(pArrDelay[i]);
+	}
+
+	pSndKit->m_aSounds.push_back(oSndKitObj);
+}
+
+
+ID CSoundManager::sndkitGetID(const char *szName)
+{
+	for (int i = 0, il = m_aSoundKits.size(); i < il; ++i)
+	{
+		if (stricmp(m_aSoundKits[i]->m_szName, szName) == 0)
+			return i;
+	}
+
+	return SOUND_FAIL_ID;
+}
+
+ID CSoundManager::sndkitGetChannel(ID idSndKit)
+{
+	SOUND_SNDKIT_PRECOND(idSndKit, SOUND_FAIL_ID);
+
+	return m_aSoundKits[idSndKit]->m_idChannel;
+}
+
+
+void CSoundManager::sndkitGetName(ID idSndKit, char *szName)
+{
+	SOUND_SNDKIT_PRECOND(idSndKit, _VOID);
+
+	strcpy(szName, m_aSoundKits[idSndKit]->m_szName);
+}
+
+
+void CSoundManager::sndkitDelete(ID idSndKit)
+{
+	SOUND_SNDKIT_PRECOND(idSndKit, _VOID);
+
+	СSoundKit *pSndKit = m_aSoundKits[idSndKit];
+
+	for (int i = 0, il = pSndKit->m_aSounds.size(); i < il; ++i)
+	{
+		soundDelete(pSndKit->m_aSounds[i].m_id);
+	}
+
+	mem_delete(m_aSoundKits[idSndKit]);
+}
+
+
+void CSoundManager::sndkitDeleteAll()
+{
+	for (int i = 0, il = m_aSoundKits.size(); i < il; ++i)
+	{
+		sndkitDelete(i);
+	}
+}
+
+
+uint64_t CSoundManager::sndkitPlay(ID idSndKit, uint64_t id2, const float3 *pPos, float fVolume, float fPan)
+{
+	SOUND_SNDKIT_PRECOND(idSndKit, SOUND_FAIL_ID);
+
+	СSoundKit *pSndKit = m_aSoundKits[idSndKit];
+
+	// если канал проигрывается
+	SOUND_CHANNEL_PLAYING(pSndKit->m_idChannel, ((id2 != SOUND_SNDKIT_INSTANCE_BLOCK && id2 != SOUND_SNDKIT_INSTANCE_NOTBLOCK) ? id2 : SOUND_FAIL_ID));
+
+	// если id2 валиден и инстанс проигрывается
+	if ((id2 != SOUND_SNDKIT_INSTANCE_BLOCK && id2 != SOUND_SNDKIT_INSTANCE_NOTBLOCK) && soundInstancePlaying(pSndKit->m_aSounds[SOUND_DECODE2ID_HI(id2)].m_id, SOUND_DECODE2ID_LO(id2)))
+		return id2;
+
+	// если id2 валиден то освобождаем инстанс
+	if (id2 != SOUND_SNDKIT_INSTANCE_BLOCK && id2 != SOUND_SNDKIT_INSTANCE_NOTBLOCK)
+		soundInstanceFree(pSndKit->m_aSounds[SOUND_DECODE2ID_HI(id2)].m_id, SOUND_DECODE2ID_LO(id2));
+
+	ID idRand = rand() % (pSndKit->m_aSounds.size());
+	ID idSndInstance = -1;
+
+	UINT *pArr = 0;
+	int iSizeArr = pSndKit->m_aSounds[idRand].m_aDelays.size();
+
+	if (iSizeArr > 0)
+		pArr = &(pSndKit->m_aSounds[idRand].m_aDelays[0]);
+
+	if (pSndKit->m_is3D)
+	{
+		if (!pPos)
+		{
+			LibReport(REPORT_MSG_LEVEL_ERROR, "%s - unresolved call function playing 3d sound without position", GEN_MSG_LOCATION);
+			return SOUND_FAIL_ID;
+		}
+
+		idSndInstance = soundInstancePlay(pSndKit->m_aSounds[idRand].m_id, id2 != SOUND_SNDKIT_INSTANCE_NOTBLOCK, false, pArr, iSizeArr, pPos, (fVolume < 0 ? pSndKit->m_aSounds[idRand].m_fVolume : fVolume));
+	}
+	else
+		idSndInstance = soundInstancePlay(pSndKit->m_aSounds[idRand].m_id, id2 != SOUND_SNDKIT_INSTANCE_NOTBLOCK, false, pArr, iSizeArr, 0, (fVolume < 0 ? pSndKit->m_aSounds[idRand].m_fVolume : fVolume), fPan);
+	
+	/*if (idSndInstance > 0)
+	{
+		CSound* snd = m_aSounds[pSndKit->m_aSounds[SOUND_DECODE2ID_HI(id2)].m_id];
+		SOUND_SNDINSTANCE_BUSY busy = snd->m_aInstances[SOUND_DECODE2ID_LO(id2)].m_busy;
+		int qwerty = 0;
+	}*/
+	
+	//ibReport(REPORT_MSG_LEVEL_NOTICE, "idSndInstance = %d\n", idSndInstance);
+	return SOUND_ENCODE2ID(idRand, idSndInstance);
+}
+
+
+void CSoundManager::sndkitStop(ID idSndKit, uint64_t id2)
+{
+	SOUND_SNDKIT_PRECOND(idSndKit, _VOID);
+
+	if (id2 == SOUND_SNDKIT_INSTANCE_BLOCK)
+		return;
+
+	СSoundKit *pSndKit = m_aSoundKits[idSndKit];
+
+	soundInstanceStop(pSndKit->m_aSounds[SOUND_DECODE2ID_HI(id2)].m_id, SOUND_DECODE2ID_LO(id2));
+}
+
+//##########################################################################
+
+void CSoundManager::channelAdd(ID idChannel, bool isPlaying)
+{
+	SOUND_CHANNEL_PRECOND(idChannel, _VOID);
+		
+	if (m_aChannels[idChannel] == SOUND_CHANNEL_NONE)
+		m_aChannels[idChannel] = isPlaying;
+}
+
+bool CSoundManager::channelExists(ID idChannel)
+{
+	SOUND_CHANNEL_PRECOND(idChannel, false);
+
+	return (m_aChannels[idChannel] != SOUND_CHANNEL_NONE);
+}
+
+int CSoundManager::channelGetSndCount(ID idChannel)
+{
+	SOUND_CHANNEL_PRECOND(idChannel, SOUND_CHANNEL_NONE);
+
+	int iCount = 0;
+	for (int i = 0, il = m_aSounds.size(); i < il; ++i)
+	{
+		if (m_aSounds[i]->m_idChannel == idChannel)
+			++iCount;
+	}
+
+	return iCount;
+}
+
+void CSoundManager::channelPlay(ID idChannel)
+{
+	SOUND_CHANNEL_PRECOND(idChannel, _VOID);
+
+	for (int i = 0, il = m_aSounds.size(); i < il; ++i)
+	{
+		if (m_aSounds[i] && m_aSounds[i]->m_idChannel == idChannel)
+		{
+			channelSndPlay(idChannel, i);
+		}
+	}
+
+	m_aChannels[idChannel] = SOUND_CHANNEL_PLAY;
+}
+
+bool CSoundManager::channelPlaying(ID idChannel)
+{
+	SOUND_CHANNEL_PRECOND(idChannel, false);
+
+	return m_aChannels[idChannel];
+}
+
+void CSoundManager::channelStop(ID idChannel)
+{
+	SOUND_CHANNEL_PRECOND(idChannel, _VOID);
+
+	for (int i = 0, il = m_aSounds.size(); i < il; ++i)
+	{
+		if (m_aSounds[i] && m_aSounds[i]->m_idChannel == idChannel)
+		{
+			channelSndStop(idChannel, i);
+		}
+	}
+
+	m_aChannels[idChannel] = SOUND_CHANNEL_STOP;
+}
+
+void CSoundManager::channelPlayOnly(ID idChannel)
+{
+	SOUND_CHANNEL_PRECOND(idChannel, _VOID);
+
+	for (int i = 0, il = m_aSounds.size(); i < il; ++i)
+	{
+		if (m_aSounds[i])
+		{
+			if (m_aSounds[i]->m_idChannel == idChannel)
+			{
+				channelSndPlay(idChannel, i);
+			}
+			else
+			{
+				channelSndStop(idChannel, i);
+			}
+		}
+	}
+}
+
+void CSoundManager::soundResumePlayDelay(CSoundBase *pSndBase)
+{
+	if (!pSndBase || !(pSndBase->m_isPlayDelay))
+		return;
+
+	//если ключ валиден
+	if (pSndBase->oPlayDelay.m_iCurrPlayDelay >= 0 && pSndBase->oPlayDelay.m_aPlayDelay.size() > pSndBase->oPlayDelay.m_iCurrPlayDelay)
+	{
+		//если текущее значение задержка
+		if (pSndBase->oPlayDelay.m_aPlayDelay[pSndBase->oPlayDelay.m_iCurrPlayDelay].m_isDelay)
+			pSndBase->oPlayDelay.m_uiPlayDelayStart = GetTickCount() - pSndBase->oPlayDelay.m_uiPlayDelayStart;
+		else
+			pSndBase->m_pSoundBuffer->Play(0, 0, 0);
+	}
+	//иначе ключ невалиден, просто доигрываем
+	else
+		pSndBase->m_pSoundBuffer->Play(0, 0, 0);
+}
+
+void CSoundManager::channelSndPlay(ID idChannel, ID idSound)
+{
+	if (idSound < m_aSounds.size() && idSound >= 0 && m_aSounds[idSound] && m_aSounds[idSound]->m_idChannel == idChannel)
+	{
+		CSound *pSnd = m_aSounds[idSound];
+		DWORD dwStatus = 0;
+
+		if (!(pSnd->m_isPlayDelay) && SUCCEEDED(pSnd->m_pSoundBuffer->GetStatus(&dwStatus)) && !(dwStatus & DSBSTATUS_PLAYING) && pSnd->m_state == SOUND_OBJSTATE_PLAY)
+			pSnd->m_pSoundBuffer->Play(0, 0, (pSnd->m_uiStreamSize || pSnd->m_isLooping ? DSBPLAY_LOOPING : 0));
+		//если воспроизведение с задержками
+		else if (pSnd->m_isPlayDelay && pSnd->m_state == SOUND_OBJSTATE_PLAY)			
+			soundResumePlayDelay(pSnd);
+			
+
+		for (int k = 0, kl = pSnd->m_aInstances.size(); k < kl; ++k)
+		{
+			//TODO: доделать восстановление проигрывания с задержками для инстансов
+
+			if (pSnd->m_aInstances[k].m_state == SOUND_OBJSTATE_PAUSE)
+			{
+				pSnd->m_aInstances[k].m_state = SOUND_OBJSTATE_PLAY;
+				
+				if (!(pSnd->m_isPlayDelay))
+					pSnd->m_aInstances[k].m_pSoundBuffer->Play(0, 0, (pSnd->m_aInstances[k].m_isLooping ? DSBPLAY_LOOPING : 0));
+				else
+					soundResumePlayDelay(&(pSnd->m_aInstances[k]));
+			}
+		}
+	}
+}
+
+void CSoundManager::channelSndStop(ID idChannel, ID idSound)
+{
+	if (idSound < m_aSounds.size() && idSound >= 0 && m_aSounds[idSound] && m_aSounds[idSound]->m_idChannel == idChannel)
+	{
+		CSound *pSnd = m_aSounds[idSound];
+
+		if (pSnd->m_isPlayDelay)
+		{
+			if (pSnd->oPlayDelay.m_iCurrPlayDelay >= 0 && pSnd->oPlayDelay.m_aPlayDelay.size() > pSnd->oPlayDelay.m_iCurrPlayDelay && pSnd->oPlayDelay.m_aPlayDelay[pSnd->oPlayDelay.m_iCurrPlayDelay].m_isDelay)
+				pSnd->oPlayDelay.m_uiPlayDelayStart = GetTickCount() - pSnd->oPlayDelay.m_uiPlayDelayStart;
+		}
+
+		pSnd->m_pSoundBuffer->Stop();
+		DWORD dwStatus = 0;
+		CSoundInstance *pSndInst = 0;
+
+		for (int k = 0, kl = pSnd->m_aInstances.size(); k < kl; ++k)
+		{
+			pSndInst = &(pSnd->m_aInstances[k]);
+			dwStatus = 0;
+
+			if (pSndInst->m_state == SOUND_OBJSTATE_PLAY && SUCCEEDED(pSndInst->m_pSoundBuffer->GetStatus(&dwStatus)) && (dwStatus & DSBSTATUS_PLAYING))
+			{
+				pSndInst->m_pSoundBuffer->Stop();
+				pSndInst->m_state = SOUND_OBJSTATE_PAUSE;
+			}
+
+			if (pSndInst->m_isPlayDelay)
+			{
+				if (pSndInst->oPlayDelay.m_iCurrPlayDelay >= 0 && pSndInst->oPlayDelay.m_aPlayDelay.size() > pSndInst->oPlayDelay.m_iCurrPlayDelay && pSndInst->oPlayDelay.m_aPlayDelay[pSndInst->oPlayDelay.m_iCurrPlayDelay].m_isDelay)
+					pSndInst->oPlayDelay.m_uiPlayDelayStart = GetTickCount() - pSndInst->oPlayDelay.m_uiPlayDelayStart;
+			}
+		}
+	}
+}
+
+//##########################################################################
+
+void CSoundManager::init(HWND hwnd)
+{
+	if (FAILED(DirectSoundCreate8(NULL, &m_pDeviceSound, NULL)))
 	{
 		LibReport(REPORT_MSG_LEVEL_ERROR, "%s - could not create sound device", GEN_MSG_LOCATION);
 		return;// SOUND_INIT_ERR_INIT;
 	}
 
-	if (FAILED(DeviceSound->SetCooperativeLevel(hwnd, DSSCL_EXCLUSIVE)))
+	if (FAILED(m_pDeviceSound->SetCooperativeLevel(hwnd, DSSCL_EXCLUSIVE)))
 	{
 		LibReport(REPORT_MSG_LEVEL_ERROR, "%s - could not create cooperative level", GEN_MSG_LOCATION);
 		return;// SOUND_INIT_ERR_CL;
@@ -104,7 +491,7 @@ void MainSound::Init(HWND hwnd)
 	dsbd.dwBufferBytes = 0;
 	dsbd.lpwfxFormat = 0;
 
-	if (FAILED(DeviceSound->CreateSoundBuffer(&dsbd, &DSPrimary, NULL)))
+	if (FAILED(m_pDeviceSound->CreateSoundBuffer(&dsbd, &m_pPrimaryBuffer, NULL)))
 	{
 		LibReport(REPORT_MSG_LEVEL_ERROR, "%s - could not create primary buffer", GEN_MSG_LOCATION);
 		return;// SOUND_INIT_ERR_PRIM_BUF;
@@ -120,28 +507,28 @@ void MainSound::Init(HWND hwnd)
 	wfex.nBlockAlign = (wfex.wBitsPerSample / 8) * wfex.nChannels;
 	wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign;
 
-	if (FAILED(DSPrimary->SetFormat(&wfex)))
+	if (FAILED(m_pPrimaryBuffer->SetFormat(&wfex)))
 	{
 		LibReport(REPORT_MSG_LEVEL_ERROR, "%s - could not init format", GEN_MSG_LOCATION);
 		return;// SOUND_INIT_ERR_SET_FORMAT;
 	}
 
-	DSPrimary->SetVolume(0);
-	DSPrimary->Play(0, 0, DSBPLAY_LOOPING);
+	m_pPrimaryBuffer->SetVolume(0);
+	m_pPrimaryBuffer->Play(0, 0, DSBPLAY_LOOPING);
 }
 
 //
 
-SOUND_FILEFORMAT MainSound::FileFormat(const char* file)
+SOUND_FILEFORMAT CSoundManager::fileFormat(const char* file)
 {
 	FILE *fp;
 
 	if (!(fp = fopen(file, "rb")))
 		return SOUND_FILEFORMAT_UNKNOWN;
 
-	SoundWaveHeader Hdr;
+	CSoundWaveHeader Hdr;
 	fseek(fp, 0, SEEK_SET);
-	fread(&Hdr, 1, sizeof(SoundWaveHeader), fp);
+	fread(&Hdr, 1, sizeof(CSoundWaveHeader), fp);
 
 	if (memcmp(Hdr.RiffSig, "RIFF", 4) == 0 || memcmp(Hdr.Sig, "WAVE", 4) == 0 || memcmp(Hdr.FormatSig, "fmt ", 4) == 0)
 	{
@@ -162,76 +549,76 @@ SOUND_FILEFORMAT MainSound::FileFormat(const char* file)
 
 //#############################################################################
 
-void MainSound::Load(Sound* snd, const char* fpath, SOUND_FILEFORMAT fmt)
+void CSoundManager::load(CSound* snd, const char* fpath, SOUND_FILEFORMAT fmt)
 {
 	if (fmt == SOUND_FILEFORMAT_OGG)
-		LoadOGG(snd, fpath);
+		loadOGG(snd, fpath);
 	else if (fmt == SOUND_FILEFORMAT_WAV)
-		LoadWAV(snd, fpath);
+		loadWAV(snd, fpath);
 }
 
-void MainSound::LoadWAV(Sound* snd, const char* fpath)
+void CSoundManager::loadWAV(CSound* snd, const char* fpath)
 {
-	SoundWaveHeader Hdr;
-	snd->StreamFile = fopen(fpath, "rb");
+	CSoundWaveHeader Hdr;
+	snd->m_pStream = fopen(fpath, "rb");
 
-	fseek(snd->StreamFile, 0, SEEK_SET);
-	fread(&Hdr, 1, sizeof(SoundWaveHeader), snd->StreamFile);
+	fseek(snd->m_pStream, 0, SEEK_SET);
+	fread(&Hdr, 1, sizeof(CSoundWaveHeader), snd->m_pStream);
 
-	snd->SizeFull = (Hdr.ChunkSize + (sizeof(char)* 4 + sizeof(int32_t))) - sizeof(SoundWaveHeader);
+	snd->m_uiSizeFull = (Hdr.ChunkSize + (sizeof(char)* 4 + sizeof(int32_t))) - sizeof(CSoundWaveHeader);
 
-	if (snd->StreamSize == 0)
-		Hdr.DataSize = snd->SizeFull;
+	if (snd->m_uiStreamSize == 0)
+		Hdr.DataSize = snd->m_uiSizeFull;
 	else
-		Hdr.DataSize = snd->StreamSize;
+		Hdr.DataSize = snd->m_uiStreamSize;
 	
-	if (!(snd->DSBuffer = SoundBufferCreate(&Hdr)))
+	if (!(snd->m_pSoundBuffer = soundBufferCreate(&Hdr)))
 	{
-		LibReport(REPORT_MSG_LEVEL_ERROR, "%s - could not create sound buffer [%s]", GEN_MSG_LOCATION, snd->RPath);
+		LibReport(REPORT_MSG_LEVEL_ERROR, "%s - could not create sound buffer [%s]", GEN_MSG_LOCATION, snd->m_szRPath);
 		return;
 	}
 
-	fseek(snd->StreamFile, sizeof(SoundWaveHeader), SEEK_SET);
+	fseek(snd->m_pStream, sizeof(CSoundWaveHeader), SEEK_SET);
 
-	SoundDataWAVLoad(snd->DSBuffer, 0, snd->StreamFile, Hdr.DataSize, 0);
+	soundDataWAVLoad(snd->m_pSoundBuffer, 0, snd->m_pStream, Hdr.DataSize, 0);
 
-	snd->LengthSec = snd->StreamSize / (Hdr.BytesPerSec);
-	snd->ChannelsCount = Hdr.Channels;
-	snd->RateSample = Hdr.SampleRate;
-	snd->BitsPerSample = Hdr.BitsPerSample;
-	snd->BytesPerSec = ((snd->BitsPerSample / 8) * snd->ChannelsCount) * snd->RateSample;
+	snd->m_iLengthSec = snd->m_uiStreamSize / (Hdr.BytesPerSec);
+	snd->m_iChannelsCount = Hdr.Channels;
+	snd->m_iSampleRate = Hdr.SampleRate;
+	snd->m_iBitsPerSample = Hdr.BitsPerSample;
+	snd->m_uiBytesPerSec = ((snd->m_iBitsPerSample / 8) * snd->m_iChannelsCount) * snd->m_iSampleRate;
 
-	if (snd->StreamSize == 0)
+	if (snd->m_uiStreamSize == 0)
 	{
-		fclose(snd->StreamFile);
+		fclose(snd->m_pStream);
 	}
 	else
 	{
-		snd->Split1Size = snd->StreamSize / 4;
-		snd->Split2Size = snd->Split1Size * 2;
-		snd->Split3Size = snd->Split1Size * 3;
+		snd->m_uiSplit1Size = snd->m_uiStreamSize / 4;
+		snd->m_uiSplit2Size = snd->m_uiSplit1Size * 2;
+		snd->m_uiSplit3Size = snd->m_uiSplit1Size * 3;
 
-		snd->BF1 = false;
-		snd->BF2 = false;
-		snd->BF3 = false;
-		snd->BF4 = false;
+		snd->m_isWork1 = false;
+		snd->m_isWork2 = false;
+		snd->m_isWork3 = false;
+		snd->m_isWork4 = false;
 
-		snd->IsStarting = true;
+		snd->m_isStarting = true;
 
-		snd->RePlayCount = 0;
-		double tmpCRPE = double(snd->SizeFull) / double(snd->StreamSize);
+		snd->m_iRePlayCount = 0;
+		double tmpCRPE = double(snd->m_uiSizeFull) / double(snd->m_uiStreamSize);
 		float Count = 0;
 
 		while (1)
 		{
 			if (tmpCRPE > Count && tmpCRPE < Count + 1)
 			{
-				snd->RePlayEndCount = Count + 1;
+				snd->m_iRePlayEndCount = Count + 1;
 				break;
 			}
 			else if (tmpCRPE == Count)
 			{
-				snd->RePlayEndCount = Count;
+				snd->m_iRePlayEndCount = Count;
 				break;
 			}
 			Count++;
@@ -239,10 +626,10 @@ void MainSound::LoadWAV(Sound* snd, const char* fpath)
 	}
 }
 
-IDirectSoundBuffer8* MainSound::SoundBufferCreate(SoundWaveHeader* hdr)
+IDirectSoundBuffer8* CSoundManager::soundBufferCreate(CSoundWaveHeader* hdr)
 {
 	IDirectSoundBuffer  *DSB;
-	IDirectSoundBuffer8 *DSBuffer;
+	IDirectSoundBuffer8 *m_pSoundBuffer;
 	DSBUFFERDESC dsbd;
 	WAVEFORMATEX wfex;
 
@@ -261,19 +648,19 @@ IDirectSoundBuffer8* MainSound::SoundBufferCreate(SoundWaveHeader* hdr)
 	dsbd.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY | DSBCAPS_LOCSOFTWARE;
 	dsbd.dwBufferBytes = hdr->DataSize;
 	dsbd.lpwfxFormat = &wfex;
-	if (FAILED(DeviceSound->CreateSoundBuffer(&dsbd, &DSB, NULL)))
+	if (FAILED(m_pDeviceSound->CreateSoundBuffer(&dsbd, &DSB, NULL)))
 		return NULL;
 
-	if (FAILED(DSB->QueryInterface(IID_IDirectSoundBuffer8, (void**)&DSBuffer)))
+	if (FAILED(DSB->QueryInterface(IID_IDirectSoundBuffer8, (void**)&m_pSoundBuffer)))
 	{
 		DSB->Release();
 		return NULL;
 	}
 
-	return DSBuffer;
+	return m_pSoundBuffer;
 }
 
-void MainSound::SoundDataWAVLoad(IDirectSoundBuffer8* DSBuffer, long LockPos, FILE* data, long Size, DWORD flag)
+void CSoundManager::soundDataWAVLoad(IDirectSoundBuffer8* m_pSoundBuffer, int LockPos, FILE* data, int Size, UINT flag)
 {
 	BYTE  *Ptr1, *Ptr2;
 	DWORD Size1, Size2;
@@ -281,113 +668,113 @@ void MainSound::SoundDataWAVLoad(IDirectSoundBuffer8* DSBuffer, long LockPos, FI
 	if (!Size)
 		return;
 
-	if (FAILED(DSBuffer->Lock(LockPos, Size, (void**)&Ptr1, &Size1, (void**)&Ptr2, &Size2, flag)))
+	if (FAILED(m_pSoundBuffer->Lock(LockPos, Size, (void**)&Ptr1, &Size1, (void**)&Ptr2, &Size2, flag)))
 		return;
 
 	fread(Ptr1, 1, Size1, data);
 	if (Ptr2)
 		fread(Ptr2, 1, Size2, data);
 
-	DSBuffer->Unlock(Ptr1, Size1, Ptr2, Size2);
+	m_pSoundBuffer->Unlock(Ptr1, Size1, Ptr2, Size2);
 }
 
 /////////////////////////////////////////////////////////////////////////////
 
-void MainSound::LoadOGG(Sound* snd, const char* fpath)
+void CSoundManager::loadOGG(CSound* snd, const char* fpath)
 {
 	OggVorbis_File ogg;
 
-	snd->StreamFile = fopen(fpath, "rb");
+	snd->m_pStream = fopen(fpath, "rb");
 
-	if (snd->StreamFile == NULL)
+	if (snd->m_pStream == NULL)
 		return;
 
 	if (ov_fopen(fpath, &ogg))
 	{
-		LibReport(REPORT_MSG_LEVEL_ERROR, "%s - error reading [%s]", GEN_MSG_LOCATION, snd->RPath);
+		LibReport(REPORT_MSG_LEVEL_ERROR, "%s - error reading [%s]", GEN_MSG_LOCATION, snd->m_szRPath);
 		return;
 	}
 
-	snd->VorbisFile = new OggVorbis_File;
+	snd->m_pVorbisFile = new OggVorbis_File;
 
 	ov_callbacks cb;
-	cb.close_func = ogg_close;
-	cb.read_func = ogg_read;
-	cb.seek_func = ogg_seek;
-	cb.tell_func = ogg_tell;
+	cb.close_func = OggCallbackClose;
+	cb.read_func = OggCallbackRead;
+	cb.seek_func = OggCallbackSeek;
+	cb.tell_func = OggCallbackTell;
 
-	ov_open_callbacks(snd->StreamFile, snd->VorbisFile, 0, 0, cb);
+	ov_open_callbacks(snd->m_pStream, snd->m_pVorbisFile, 0, 0, cb);
 
 	vorbis_info *vi = ov_info(&ogg, -1);
 
 	if (!vi)
 	{
-		LibReport(REPORT_MSG_LEVEL_ERROR, "%s - error reading (info) [%s]", GEN_MSG_LOCATION, snd->RPath);
+		LibReport(REPORT_MSG_LEVEL_ERROR, "%s - error reading (info) [%s]", GEN_MSG_LOCATION, snd->m_szRPath);
 		return;
 	}
 
-	snd->LengthSec = float(ov_pcm_total(snd->VorbisFile, -1)) / float(vi->rate);
-	snd->ChannelsCount = vi->channels;
-	snd->RateSample = vi->rate;
-	snd->BitsPerSample = SOUND_OGG_BITS_PER_SAMPLE;
-	snd->BytesPerSec = ((snd->BitsPerSample / 8) * snd->ChannelsCount) * snd->RateSample;
-	snd->SizeFull = ov_pcm_total(snd->VorbisFile, -1) * 2 * vi->channels;
+	snd->m_iLengthSec = float(ov_pcm_total(snd->m_pVorbisFile, -1)) / float(vi->rate);
+	snd->m_iChannelsCount = vi->channels;
+	snd->m_iSampleRate = vi->rate;
+	snd->m_iBitsPerSample = SOUND_OGG_BITS_PER_SAMPLE;
+	snd->m_uiBytesPerSec = ((snd->m_iBitsPerSample / 8) * snd->m_iChannelsCount) * snd->m_iSampleRate;
+	snd->m_uiSizeFull = ov_pcm_total(snd->m_pVorbisFile, -1) * 2 * vi->channels;
 
-	SoundWaveHeader hdr;
+	CSoundWaveHeader hdr;
 	hdr.Channels = vi->channels;
 	hdr.SampleRate = vi->rate;
 	hdr.BitsPerSample = SOUND_OGG_BITS_PER_SAMPLE;
 
-	if (snd->StreamSize == 0)
-		hdr.DataSize = snd->SizeFull;
+	if (snd->m_uiStreamSize == 0)
+		hdr.DataSize = snd->m_uiSizeFull;
 	else
-		hdr.DataSize = snd->StreamSize;
+		hdr.DataSize = snd->m_uiStreamSize;
 
-	snd->DSBuffer = SoundBufferCreate(&hdr);
+	snd->m_pSoundBuffer = soundBufferCreate(&hdr);
 
-	if (!snd->DSBuffer)
+	if (!snd->m_pSoundBuffer)
 	{
-		LibReport(REPORT_MSG_LEVEL_ERROR, "%s - could not create sound buffer [%s]", GEN_MSG_LOCATION, snd->RPath);
+		LibReport(REPORT_MSG_LEVEL_ERROR, "%s - could not create sound buffer [%s]", GEN_MSG_LOCATION, snd->m_szRPath);
 		return;
 	}
 
-	SoundDataOGGLoad(snd->VorbisFile, snd->DSBuffer, 0, hdr.DataSize, 0);
+	soundDataOGGLoad(snd->m_pVorbisFile, snd->m_pSoundBuffer, 0, hdr.DataSize, 0);
 
-	if (snd->StreamSize == 0)
+	if (snd->m_uiStreamSize == 0)
 	{
-		fclose(snd->StreamFile);
+		fclose(snd->m_pStream);
 		ov_clear(&ogg);
-		ov_clear(snd->VorbisFile);
-		mem_delete(snd->VorbisFile);
-		snd->VorbisFile = 0;
+		ov_clear(snd->m_pVorbisFile);
+		mem_delete(snd->m_pVorbisFile);
+		snd->m_pVorbisFile = 0;
 	}
 	else
 	{
-		snd->Split1Size = snd->StreamSize / 4;
-		snd->Split2Size = snd->Split1Size * 2;
-		snd->Split3Size = snd->Split1Size * 3;
+		snd->m_uiSplit1Size = snd->m_uiStreamSize / 4;
+		snd->m_uiSplit2Size = snd->m_uiSplit1Size * 2;
+		snd->m_uiSplit3Size = snd->m_uiSplit1Size * 3;
 
-		snd->BF1 = false;
-		snd->BF2 = false;
-		snd->BF3 = false;
-		snd->BF4 = false;
+		snd->m_isWork1 = false;
+		snd->m_isWork2 = false;
+		snd->m_isWork3 = false;
+		snd->m_isWork4 = false;
 
-		snd->IsStarting = true;
+		snd->m_isStarting = true;
 
-		snd->RePlayCount = 0;
-		double tmpCRPE = double(snd->SizeFull) / double(snd->StreamSize);
+		snd->m_iRePlayCount = 0;
+		double tmpCRPE = double(snd->m_uiSizeFull) / double(snd->m_uiStreamSize);
 		float Count = 0;
 
 		while (1)
 		{
 			if (tmpCRPE > Count && tmpCRPE < Count + 1)
 			{
-				snd->RePlayEndCount = Count + 1;
+				snd->m_iRePlayEndCount = Count + 1;
 				break;
 			}
 			else if (tmpCRPE == Count)
 			{
-				snd->RePlayEndCount = Count;
+				snd->m_iRePlayEndCount = Count;
 				break;
 			}
 			Count++;
@@ -396,7 +783,7 @@ void MainSound::LoadOGG(Sound* snd, const char* fpath)
 	//return SOUND_OK;
 }
 
-void MainSound::SoundDataOGGLoad(OggVorbis_File* VorbisFile, IDirectSoundBuffer8 *DSBuffer, long LockPos, long Size, DWORD flag)
+void CSoundManager::soundDataOGGLoad(OggVorbis_File* VorbisFile, IDirectSoundBuffer8 *m_pSoundBuffer, int LockPos, int Size, UINT flag)
 {
 	char  *Ptr1, *Ptr2;
 	DWORD Size1, Size2;
@@ -404,7 +791,7 @@ void MainSound::SoundDataOGGLoad(OggVorbis_File* VorbisFile, IDirectSoundBuffer8
 	if (!Size)
 		return;
 
-	if (FAILED(DSBuffer->Lock(LockPos, Size, (void**)&Ptr1, &Size1, (void**)&Ptr2, &Size2, flag)))
+	if (FAILED(m_pSoundBuffer->Lock(LockPos, Size, (void**)&Ptr1, &Size1, (void**)&Ptr2, &Size2, flag)))
 		return;
 
 	DWORD total_read = 0;
@@ -457,355 +844,489 @@ void MainSound::SoundDataOGGLoad(OggVorbis_File* VorbisFile, IDirectSoundBuffer8
 		}
 	}
 
-	DSBuffer->Unlock(Ptr1, Size1, Ptr2, Size2);
+	m_pSoundBuffer->Unlock(Ptr1, Size1, Ptr2, Size2);
 }
 
 //#############################################################################
 
-ID MainSound::SoundCreate2d(const char *file, bool looping, DWORD size_stream)
+ID CSoundManager::soundCreate2d(const char *szFile, ID idChannel, UINT uiSizeStream)
 {
-	if (!file)
-		return -1;
+	if (!szFile)
+		return SOUND_FAIL_ID;
+
+	String sFileData = szFile;
+	float fDistAudibleData = -1.f;
+	float fVolumeData = -1.f;
+	Array<UINT> aDelaysData;
+
+	SndGetDataFromStr(szFile, sFileData, fDistAudibleData, fVolumeData, aDelaysData);
 
 	char fullpath[SOUND_MAX_SIZE_STDPATH + SOUND_MAX_SIZE_PATH];
-	sprintf(fullpath, "%s%s", Core_RStringGet(G_RI_STRING_PATH_GS_SOUNDS), file);
+	sprintf(fullpath, "%s%s", Core_RStringGet(G_RI_STRING_PATH_GS_SOUNDS), sFileData.c_str());
 
 	if (!Core_0FileExists(fullpath))
 	{
 		LibReport(REPORT_MSG_LEVEL_ERROR, "%s - file not found [%s]", GEN_MSG_LOCATION, fullpath);
-		return -1;
+		return SOUND_FAIL_ID;
 	}
 
-	SOUND_FILEFORMAT fmt = FileFormat(fullpath);
+	SOUND_FILEFORMAT fmt = fileFormat(fullpath);
 
 	if (fmt == SOUND_FILEFORMAT_UNKNOWN)
 	{
-		LibReport(REPORT_MSG_LEVEL_ERROR, "%s - unknown format [%s]", GEN_MSG_LOCATION, file);
-		return -1;
+		LibReport(REPORT_MSG_LEVEL_ERROR, "%s - unknown format [%s]", GEN_MSG_LOCATION, sFileData.c_str());
+		return SOUND_FAIL_ID;
 	}
 
-	Sound* snd = new Sound();
-	strcpy(snd->RPath, file);
-	snd->Format = fmt;
-	snd->IsLooping = looping;
+	channelAdd(idChannel);
+
+	CSound *pSnd = new CSound();
+
+	if (fDistAudibleData > 0.f)
+		pSnd->m_fDistAudible = fDistAudibleData;
 
-	snd->StreamSize = 0;
-	if (size_stream > 0)
+	if (fVolumeData > -1.f)
+		pSnd->m_fVolume = fVolumeData;
+
+	strcpy(pSnd->m_szRPath, szFile);
+	pSnd->m_format = fmt;
+
+	pSnd->m_uiStreamSize = 0;
+	if (uiSizeStream > 0)
 	{
-		if (size_stream < SOUND_MIN_SIZE_STREAM)
-			snd->StreamSize = SOUND_MIN_SIZE_STREAM;
+		if (uiSizeStream < SOUND_MIN_SIZE_STREAM)
+			pSnd->m_uiStreamSize = SOUND_MIN_SIZE_STREAM;
 		else
-			snd->StreamSize = size_stream;
+			pSnd->m_uiStreamSize = uiSizeStream;
 	}
+	
+	if (uiSizeStream == 0 && aDelaysData.size() > 0)
+	{
+		soundInitPlayDelay(pSnd, &(aDelaysData[0]), aDelaysData.size());
+	}
+
+	load(pSnd, fullpath, fmt);
 
-	Load(snd, fullpath, fmt);
+	DWORD dwFrec;
+	pSnd->m_pSoundBuffer->GetFrequency(&dwFrec);
+	pSnd->m_uiFrecOrigin = dwFrec;
+	pSnd->m_id = addSound(pSnd);
+	pSnd->m_idChannel = idChannel;
+	pSnd->m_iCountLoad = 1;
 
-	snd->DSBuffer->GetFrequency(&snd->FrecOrigin);
-	snd->Id = AddSound(snd);
-	return snd->Id;
+	return pSnd->m_id;
 }
 
-ID MainSound::SoundCreate3d(const char *file, bool looping, DWORD size_stream, float dist, float shift_pan)
+ID CSoundManager::soundCreate3d(const char *file, ID idChannel, UINT size_stream, float dist)
 {
-	ID sndid = SoundCreate2d(file, looping, size_stream);
-	Sound* snd = 0;
+	ID idSnd = soundCreate2d(file, idChannel, size_stream);
+	CSound* snd = 0;
 
-	if (sndid < 0)
-		return sndid;
+	if (idSnd < 0)
+		return idSnd;
 
-	snd = ArrSounds[sndid];
-	snd->DistAudible = dist;
-	snd->Is3d = true;
-	snd->ShiftPan = shift_pan;
+	snd = m_aSounds[idSnd];
+
+	if (snd->m_fDistAudible <= 0.f)
+		snd->m_fDistAudible = dist;
+
+	snd->m_is3d = true;
+	snd->m_fShiftPan = SOUND_SHIFTPAN_3D;
+	snd->m_idChannel = idChannel;
 	
-	return sndid;
+	return idSnd;
 }
 
-ID MainSound::SoundCreate2dInst(const char *file, bool looping, DWORD size_stream)
+ID CSoundManager::soundCreate2dInst(const char *file, ID idChannel)
 {
-	ID idsnd = SoundFind2dInst(file);
-	if (idsnd >= 0)
-		return idsnd;
-	idsnd = SoundCreate2d(file, looping, size_stream);
-	AArr2dInst[file] = idsnd;
-	ArrSounds[idsnd]->IsInst = true;
-	return idsnd;
+	ID idSnd = soundFind2dInst(file, idChannel);
+
+	if (idSnd >= 0)
+	{
+		++(m_aSounds[idSnd]->m_iCountLoad);
+		return idSnd;
+	}
+
+	idSnd = soundCreate2d(file, idChannel);
+
+	char szStr[SOUND_MAX_SIZE_FULLPATH];
+	szStr[0] = 0;
+	SOUND_CREATE_NAME(szStr, idChannel, file);
+
+	m_a2dInst[szStr] = idSnd;
+	m_aSounds[idSnd]->m_isInst = true;
+	m_aSounds[idSnd]->m_idChannel = idChannel;
+	return idSnd;
 }
 
-ID MainSound::SoundCreate3dInst(const char *file, bool looping, DWORD size_stream, float dist, float shift_pan)
+ID CSoundManager::soundCreate3dInst(const char *file, ID idChannel, float dist)
 {
-	ID idsnd = SoundFind2dInst(file);
-	if (idsnd >= 0)
-		return idsnd;
-	idsnd = SoundCreate3d(file, looping, size_stream, dist, shift_pan);
-	AArr3dInst[file] = idsnd;
-	ArrSounds[idsnd]->IsInst = true;
-	return idsnd;
+	ID idSnd = soundFind3dInst(file, idChannel);
+
+	if (idSnd >= 0)
+	{
+		++(m_aSounds[idSnd]->m_iCountLoad);
+		return idSnd;
+	}
+
+	idSnd = soundCreate3d(file, idChannel, 0, dist);
+
+	char szStr[SOUND_MAX_SIZE_FULLPATH];
+	szStr[0] = 0;
+	SOUND_CREATE_NAME(szStr, idChannel, file);
+
+	m_a3dInst[szStr] = idSnd;
+	m_aSounds[idSnd]->m_isInst = true;
+	m_aSounds[idSnd]->m_idChannel = idChannel;
+
+	return idSnd;
 }
 
-ID MainSound::SoundFind2dInst(const char * file)
+ID CSoundManager::soundFind2dInst(const char *file, ID idChannel)
 {
-	ID id = -1;
+	char szStr[SOUND_MAX_SIZE_FULLPATH];
+	szStr[0] = 0;
+	SOUND_CREATE_NAME(szStr, idChannel, file);
+
+	ID id = SOUND_FAIL_ID;
 	const AssotiativeArray<AAStringNR, ID, false, 16>::Node* pNode = 0;
-	if (AArr2dInst.KeyExists(file, &pNode))
+	if (m_a2dInst.KeyExists(szStr, &pNode))
 		id = *(pNode->Val);
 
 	return id;
 }
 
-ID MainSound::SoundFind3dInst(const char * file)
+ID CSoundManager::soundFind3dInst(const char *file, ID idChannel)
 {
-	ID id = -1;
+	char szStr[SOUND_MAX_SIZE_FULLPATH];
+	szStr[0] = 0;
+	SOUND_CREATE_NAME(szStr, idChannel, file);
+
+	ID id = SOUND_FAIL_ID;
 	const AssotiativeArray<AAStringNR, ID, false, 16>::Node* pNode = 0;
-	if (AArr3dInst.KeyExists(file, &pNode))
+	if (m_a3dInst.KeyExists(szStr, &pNode))
 		id = *(pNode->Val);
 
 	return id;
 }
 
-void MainSound::SoundInstancePlay2d(ID id, int volume, int pan)
+ID CSoundManager::soundInstancePlay(ID idSound, bool isBlocked, bool isLooping, UINT *pArrDelay, int iSizeArrDelay, const float3 *pPos, float fVolume, float fPan)
 {
-	SOUND_PRECOND(id, _VOID);
+	SOUND_PRECOND(idSound, SOUND_FAIL_ID);
+
+	CSound *pSnd = m_aSounds[idSound];
 
-	Sound* snd = ArrSounds[id];
+	SOUND_CHANNEL_PLAYING(pSnd->m_idChannel, SOUND_FAIL_ID);
 
-	if (snd->StreamSize > 0)
+	if (pSnd->m_uiStreamSize > 0)
 	{
-		LibReport(REPORT_MSG_LEVEL_WARNING, "%s - can not create sound instance for streaming [%s]", GEN_MSG_LOCATION, snd->RPath);
-		return;
+		LibReport(REPORT_MSG_LEVEL_WARNING, "%s - can not create sound instance for streaming [%s]", GEN_MSG_LOCATION, pSnd->m_szRPath);
+		return SOUND_FAIL_ID;
 	}
 
-	if (snd->Is3d)
+	if (pSnd->m_is3d && !pPos)
 	{
-		LibReport(REPORT_MSG_LEVEL_WARNING, "%s - can not create 2d sound instance by 3d [%s]", GEN_MSG_LOCATION, snd->RPath);
-		return;
+		LibReport(REPORT_MSG_LEVEL_WARNING, "%s - not send position for 3d sound instance [%s]", GEN_MSG_LOCATION, pSnd->m_szRPath);
+		return SOUND_FAIL_ID;
+	}
+
+	if (!(pSnd->m_is3d) && pPos)
+	{
+		LibReport(REPORT_MSG_LEVEL_WARNING, "%s - uresolved send position for 2d sound instance [%s]", GEN_MSG_LOCATION, pSnd->m_szRPath);
+		return SOUND_FAIL_ID;
 	}
 
-	ID id_instance = -1;
-	for (UINT i = 0; i < snd->DataInstances.size(); ++i)
+	ID idInstance = -1;
+	for (int i = 0; i < pSnd->m_aInstances.size(); ++i)
 	{
-		if (!snd->DataInstances[i].busy)
+		if (pSnd->m_aInstances[i].m_busy == SOUND_SNDINSTANCE_BUSY_FREE)
 		{
-			id_instance = i;
+			idInstance = i;
 			break;
 		}
 	}
 
-	if (id_instance < 0)
+	if (idInstance < 0)
 	{
 		IDirectSoundBuffer* tsb;
 		IDirectSoundBuffer8* tsb8;
-		DeviceSound->DuplicateSoundBuffer(snd->DSBuffer, &tsb);
+		m_pDeviceSound->DuplicateSoundBuffer(pSnd->m_pSoundBuffer, &tsb);
 		if (!tsb)
 		{
-			LibReport(REPORT_MSG_LEVEL_WARNING, "%s - can not create sound instance [%s], this is big problem", GEN_MSG_LOCATION, snd->RPath);
-			return;
+			LibReport(REPORT_MSG_LEVEL_WARNING, "%s - can not create sound instance [%s], this is big problem", GEN_MSG_LOCATION, pSnd->m_szRPath);
+			return SOUND_FAIL_ID;
 		}
 		tsb->QueryInterface(IID_IDirectSoundBuffer8, (void**)&tsb8);
-		snd->DataInstances.push_back(Sound::SIData(tsb8, 0, true));
-		id_instance = snd->DataInstances.size() - 1;
+		pSnd->m_aInstances.push_back(CSoundInstance(tsb8, pSnd->m_uiBytesPerSec, (pPos ? &float3_t(*pPos) : 0), SOUND_SNDINSTANCE_BUSY_TEMP));
+		idInstance = pSnd->m_aInstances.size() - 1;
 	}
 
-	if (id_instance >= 0)
-	{
-		long tvol;
-		snd->DSBuffer->GetVolume(&tvol);
-		snd->DataInstances[id_instance].busy = true;
-		//IDirectSoundBuffer8* tsb = snd->DataInstances[id_instance].sbuffer;
-		snd->DataInstances[id_instance].sbuffer->SetVolume((tvol > -5000 ? tvol - 5000 : tvol + 5000));
-		snd->DataInstances[id_instance].sbuffer->SetCurrentPosition(0);
-		snd->DataInstances[id_instance].sbuffer->SetVolume(-10000 + (volume * 100));
-		snd->DataInstances[id_instance].sbuffer->SetPan((pan > 0) ? (10000 - (pan * 100)) - 10000 : 10000 - (10000 + (pan * 100)));
-		snd->DataInstances[id_instance].sbuffer->Play(0, 0, 0);
+	if (idInstance >= 0)
+	{
+		if (isBlocked || isLooping)
+			pSnd->m_aInstances[idInstance].m_busy = SOUND_SNDINSTANCE_BUSY_LOCKED;
+		else
+			pSnd->m_aInstances[idInstance].m_busy = SOUND_SNDINSTANCE_BUSY_TEMP;
+
+		//если установлены задержки воспроизведения
+		if (pArrDelay && iSizeArrDelay > 0 || iSizeArrDelay < 0)
+			soundInitPlayDelay(&(pSnd->m_aInstances[idInstance]), pArrDelay, iSizeArrDelay);
+
+		pSnd->m_aInstances[idInstance].m_fVolume = saturatef(fVolume);
+		
+		//если 3д звук
+		if (pSnd->m_is3d && pPos)
+		{
+			pSnd->m_aInstances[idInstance].m_pSoundBuffer->SetVolume(lerpf(-10000, 0, pSnd->m_aInstances[idInstance].m_fVolume * Snd3dComVolume((*pPos), m_vOldViewPos, pSnd->m_fDistAudible)));
+			pSnd->m_aInstances[idInstance].m_pSoundBuffer->SetPan(Snd3dComPan((*pPos), m_vOldViewPos, m_vOldViewDir, pSnd->m_fDistAudible, pSnd->m_fShiftPan));
+		}
+		//иначе фоновый
+		else
+		{
+			pSnd->m_aInstances[idInstance].m_pSoundBuffer->SetVolume(lerpf(-10000, 0, pSnd->m_aInstances[idInstance].m_fVolume));
+			pSnd->m_aInstances[idInstance].m_pSoundBuffer->SetPan((fPan > 0) ? (10000 - (fPan * 100)) - 10000 : 10000 - (10000 + (fPan * 100)));
+		}
+		
+		pSnd->m_aInstances[idInstance].m_pSoundBuffer->SetCurrentPosition(0);
+		pSnd->m_aInstances[idInstance].m_isLooping = isLooping;
+		
+		if (!(pArrDelay && iSizeArrDelay > 0))
+			pSnd->m_aInstances[idInstance].m_pSoundBuffer->Play(0, 0, ((pSnd->m_aInstances[idInstance].m_isLooping) ? DSBPLAY_LOOPING : 0));
+		
+		pSnd->m_aInstances[idInstance].m_state = SOUND_OBJSTATE_PLAY;
+
+		return idInstance;
 	}
+
+	return SOUND_FAIL_ID;
 }
 
-void MainSound::SoundInstancePlay3d(ID id, const float3* pos)
+bool CSoundManager::soundInstancePlaying(ID idSound, ID idInstance)
 {
-	SOUND_PRECOND(id, _VOID);
-
-	if (!pos)
-		return;
+	SOUND_PRECOND(idSound, false);
 
-	Sound* snd = ArrSounds[id];
+	CSound* snd = m_aSounds[idSound];
 
-	if (snd->StreamSize > 0)
+	if (idInstance >= 0)
 	{
-		LibReport(REPORT_MSG_LEVEL_WARNING, "%s - can not create sound instance for streaming [%s]", GEN_MSG_LOCATION, snd->RPath);
-		return;
+		/*DWORD dwStatus;
+		snd->m_aInstances[idInstance].m_pSoundBuffer->GetStatus(&dwStatus);
+		return (dwStatus & DSBSTATUS_PLAYING);*/
+		return (snd->m_aInstances[idInstance].m_state != SOUND_OBJSTATE_STOP);
 	}
 
-	if (!snd->Is3d)
-	{
-		LibReport(REPORT_MSG_LEVEL_WARNING, "%s - can not create 3d sound instance by 2d[%s]", GEN_MSG_LOCATION, snd->RPath);
-		return;
-	}
+	return false;
+}
 
-	ID id_instance = -1;
-	for(UINT i = 0; i < snd->DataInstances.size(); ++i)
-	{
-		if(!snd->DataInstances[i].busy)
-		{
-			id_instance = i;
-			break;
-		}
-	}
+void CSoundManager::soundInstanceStop(ID idSound, ID idInstance)
+{
+	SOUND_PRECOND(idSound, _VOID);
+
+	CSound* snd = m_aSounds[idSound];
 
-	if (id_instance < 0)
+	if (idInstance >= 0)
 	{
-		IDirectSoundBuffer* tsb;
-		IDirectSoundBuffer8* tsb8;
-		DeviceSound->DuplicateSoundBuffer(snd->DSBuffer, &tsb);
-		if (!tsb)
-		{
-			LibReport(REPORT_MSG_LEVEL_WARNING, "%s - can not create sound instance [%s], this is big problem", GEN_MSG_LOCATION, snd->RPath);
-			return;
-		}
-		tsb->QueryInterface(IID_IDirectSoundBuffer8, (void**)&tsb8);
-		snd->DataInstances.push_back(Sound::SIData(tsb8, &float3_t(*pos), true));
-		id_instance = snd->DataInstances.size() - 1;
+		snd->m_aInstances[idInstance].m_isLooping = false;
+		snd->m_aInstances[idInstance].m_pSoundBuffer->Stop();
+		snd->m_aInstances[idInstance].m_state = SOUND_OBJSTATE_STOP;
 	}
+}
 
-	if (id_instance >= 0)
-	{
-		long tvol;
-		snd->DSBuffer->GetVolume(&tvol);
-		snd->DataInstances[id_instance].sbuffer->SetVolume((tvol > -5000 ? tvol - 5000 : tvol + 5000));
+void CSoundManager::soundInstanceFree(ID idSound, ID idInstance)
+{
+	SOUND_PRECOND(idSound, _VOID);
+
+	CSound* snd = m_aSounds[idSound];
 
-		snd->DataInstances[id_instance].sbuffer->SetVolume(SOUND_3D_COM_VOLUME((*pos), OldViewPos, snd->DistAudible));
-		snd->DataInstances[id_instance].sbuffer->SetPan(SOUND_3D_COM_PAN((*pos), OldViewPos, OldViewDir, snd->DistAudible,snd->ShiftPan));
-		snd->DataInstances[id_instance].sbuffer->SetCurrentPosition(0);
-		snd->DataInstances[id_instance].sbuffer->Play(0, 0, 0);
+	if (idInstance >= 0)
+	{
+		if (snd->m_aInstances[idInstance].m_busy == SOUND_SNDINSTANCE_BUSY_LOCKED)
+			snd->m_aInstances[idInstance].m_busy = SOUND_SNDINSTANCE_BUSY_TEMP;
 	}
 }
 
-ID MainSound::AddSound(Sound* snd)
+ID CSoundManager::addSound(CSound* snd)
 {
-	for (int i = 0, l = ArrSounds.size(); i < l; ++i)
+	for (int i = 0, l = m_aSounds.size(); i < l; ++i)
 	{
-		if (ArrSounds[i] == 0)
+		if (m_aSounds[i] == 0)
 		{
-			ArrSounds[i] = snd;
+			m_aSounds[i] = snd;
 			return i;
 		}
 	}
 
-	ArrSounds.push_back(snd);
-	return ArrSounds.size() - 1;
+	m_aSounds.push_back(snd);
+	return m_aSounds.size() - 1;
 }
 
-bool MainSound::SoundIsInit(ID id)
+bool CSoundManager::soundIsInit(ID id)
 {
-	return ((ID)ArrSounds.size() > id && ArrSounds[id] != 0);
+	return ((ID)m_aSounds.size() > id && m_aSounds[id] != 0);
 }
 
-void MainSound::SoundDelete(ID id)
+void CSoundManager::soundDelete(ID id)
 {
 	SOUND_PRECOND(id, _VOID);
-	Sound* snd = ArrSounds[id];
-	if (snd->IsInst)
+
+	CSound* snd = m_aSounds[id];
+	--(snd->m_iCountLoad);
+
+	if (snd->m_iCountLoad > 0)
+		return;
+
+	if (snd->m_isInst)
 	{
-		if (snd->Is3d)
-			AArr3dInst.erase(snd->RPath);
+		char szStr[SOUND_MAX_SIZE_FULLPATH];
+		szStr[0] = 0;
+		SOUND_CREATE_NAME(szStr, snd->m_idChannel, snd->m_szRPath);
+
+		if (snd->m_is3d)
+			m_a3dInst.erase(szStr);
 		else
-			AArr2dInst.erase(snd->RPath);
+			m_a2dInst.erase(szStr);
 	}
 	mem_delete(snd);
 }
 
 //#############################################################################
 
-void MainSound::SoundPlay(ID id, int looping)
+void CSoundManager::soundPlay(ID id, bool isLooping, UINT *pArrDelay, int iSizeArrDelay)
 {
 	SOUND_PRECOND(id, _VOID);
 
-	Sound* snd = ArrSounds[id];
+	CSound *pSnd = m_aSounds[id];
+
+	if (pSnd->m_uiStreamSize != 0 && pArrDelay && iSizeArrDelay > 0)
+	{
+		LibReport(REPORT_MSG_LEVEL_ERROR, "%s - unresolved play delay for streming playing, file %s", GEN_MSG_LOCATION, pSnd->m_szRPath);
+		return;
+	}
+
+	if (!m_aChannels[pSnd->m_idChannel])
+		return;
+
+	if (pArrDelay && iSizeArrDelay > 0 || iSizeArrDelay < 0)
+		soundInitPlayDelay(pSnd, pArrDelay, iSizeArrDelay);
+
+	pSnd->m_isLooping = isLooping;
+
+	if (pSnd->m_pSoundBuffer)
+	{
+		if (pArrDelay && iSizeArrDelay > 0)
+			pSnd->m_pSoundBuffer->SetCurrentPosition(0);
+		else
+			pSnd->m_pSoundBuffer->Play(0, 0, (pSnd->m_uiStreamSize || pSnd->m_isLooping ? DSBPLAY_LOOPING : 0));
+
+		pSnd->m_state = SOUND_OBJSTATE_PLAY;
+	}
+}
 
-	if (looping >= 0)
-		snd->IsLooping = looping != 0;
+void CSoundManager::soundInitPlayDelay(CSoundBase *pSndbase, UINT *pArrDelay, int iSizeArrDelay)
+{
+	if (!pSndbase)
+		return;
 
-	if (snd->DSBuffer)
+	if (iSizeArrDelay < 0)
 	{
-		snd->DSBuffer->Play(0, 0, (snd->StreamSize || snd->IsLooping ? DSBPLAY_LOOPING : 0));
-		snd->State = SOUND_OBJSTATE_PLAY;
+		if (pSndbase->oPlayDelay.m_aPlayDelay.size() <= 0)
+		{
+			LibReport(REPORT_MSG_LEVEL_ERROR, "%s - previous delay data not init", GEN_MSG_LOCATION);
+		}
+
+		pSndbase->oPlayDelay.m_iCurrPlayDelay = 0;
+		pSndbase->m_isPlayDelay = true;
+		return;
+	}
+
+	if (pArrDelay == 0 || iSizeArrDelay == 0)
+		return;
+
+	pSndbase->oPlayDelay.m_aPlayDelay.clearFast();
+	pSndbase->oPlayDelay.m_iCurrPlayDelay = 0;
+	pSndbase->m_isPlayDelay = true;
+	pSndbase->oPlayDelay.m_uiPlayDelayStart = GetTickCount();
+
+	bool isEven = true;
+	for (int i = 0, il = iSizeArrDelay; i < il; ++i)
+	{
+		pSndbase->oPlayDelay.m_aPlayDelay.push_back(CPlayDelay::CTimeDelay(pArrDelay[i], isEven));
+		isEven = !isEven;
 	}
 }
 
-void MainSound::SoundPause(ID id)
+void CSoundManager::soundPause(ID id)
 {
 	SOUND_PRECOND(id, _VOID);
 
-	Sound* snd = ArrSounds[id];
+	CSound* snd = m_aSounds[id];
+
+	if (!m_aChannels[snd->m_idChannel])
+		return;
 
-	if (snd->DSBuffer)
+	if (snd->m_pSoundBuffer)
 	{
-		snd->DSBuffer->Stop();
-		snd->State = SOUND_OBJSTATE_PAUSE;
+		snd->m_pSoundBuffer->Stop();
+		snd->m_state = SOUND_OBJSTATE_PAUSE;
 	}
 }
 
-void MainSound::SoundStop(ID id)
+void CSoundManager::soundStop(ID id)
 {
 	SOUND_PRECOND(id, _VOID);
 
-	Sound* snd = ArrSounds[id];
+	CSound* snd = m_aSounds[id];
+
+	if (!m_aChannels[snd->m_idChannel])
+		return;
 
-	if (snd->DSBuffer)
+	if (snd->m_pSoundBuffer)
 	{
-		snd->DSBuffer->Stop();
-		snd->DSBuffer->SetCurrentPosition(0);
-		snd->State = SOUND_OBJSTATE_STOP;
+		snd->m_pSoundBuffer->Stop();
+		snd->m_pSoundBuffer->SetCurrentPosition(0);
+		snd->m_state = SOUND_OBJSTATE_STOP;
+		snd->m_isLooping = false;
+		snd->m_isPlayDelay = false;
 	}
 }
 
-void MainSound::SoundStateSet(ID id, SOUND_OBJSTATE state)
+void CSoundManager::soundSetState(ID id, SOUND_OBJSTATE state)
 {
 	SOUND_PRECOND(id, _VOID);
 
 	if (state == SOUND_OBJSTATE_PLAY)
-		SoundPlay(id);
+		soundPlay(id);
 	else if (state == SOUND_OBJSTATE_PAUSE)
-		SoundPause(id);
+		soundPause(id);
 	else if (state == SOUND_OBJSTATE_STOP)
-		SoundStop(id);
+		soundStop(id);
 }
 
-SOUND_OBJSTATE MainSound::SoundStateGet(ID id)
+SOUND_OBJSTATE CSoundManager::soundGetState(ID id)
 {
 	SOUND_PRECOND(id, SOUND_OBJSTATE_STOP);
 
-	Sound* snd = ArrSounds[id];
-	return snd->State;
+	CSound* snd = m_aSounds[id];
+	return snd->m_state;
 }
 
-void MainSound::SoundPosCurrSet(ID id, DWORD pos, int type)
+void CSoundManager::soundSetPosPlay(ID id, UINT pos)
 {
 	SOUND_PRECOND(id, _VOID);
 
-	Sound* snd = ArrSounds[id];
+	CSound* snd = m_aSounds[id];
 
 	DWORD PosInBytes = 0;
-	if (snd->DSBuffer)
+	if (snd->m_pSoundBuffer)
 	{
-		if (type == SOUND_POS_BYTES)
-		{
-			PosInBytes = pos;
-		}
-		else if (type == SOUND_POS_SEC)
-		{
-			PosInBytes = pos * snd->BytesPerSec;
-		}
-		else if (type == SOUND_POS_MLS)
-		{
-			PosInBytes = pos * (snd->BytesPerSec / 1000);
-		}
+		PosInBytes = pos * (snd->m_uiBytesPerSec / 1000);
 
-		if (snd->StreamSize)
+		if (snd->m_uiStreamSize)
 		{
 			WORD HowCountRePlay = 0;
-			for (WORD i = 0; i <= snd->RePlayEndCount; i++)
+			for (WORD i = 0; i <= snd->m_iRePlayEndCount; i++)
 			{
-				if ((i * snd->StreamSize <= PosInBytes && (i + 1) * snd->StreamSize >= PosInBytes) || i * snd->StreamSize == PosInBytes)
+				if ((i * snd->m_uiStreamSize <= PosInBytes && (i + 1) * snd->m_uiStreamSize >= PosInBytes) || i * snd->m_uiStreamSize == PosInBytes)
 				{
 					HowCountRePlay = i;
 					break;
@@ -813,392 +1334,463 @@ void MainSound::SoundPosCurrSet(ID id, DWORD pos, int type)
 			}
 
 			//wav
-			if (snd->Format == SOUND_FILEFORMAT_WAV)
-				fseek(snd->StreamFile, sizeof(SoundWaveHeader)+(HowCountRePlay  * snd->StreamSize), SEEK_SET);
+			if (snd->m_format == SOUND_FILEFORMAT_WAV)
+				fseek(snd->m_pStream, sizeof(CSoundWaveHeader)+(HowCountRePlay  * snd->m_uiStreamSize), SEEK_SET);
 			//ogg
-			else if (snd->Format == SOUND_FILEFORMAT_OGG)
-				ov_pcm_seek(snd->VorbisFile, (HowCountRePlay  * snd->StreamSize) / (2 * snd->ChannelsCount));
+			else if (snd->m_format == SOUND_FILEFORMAT_OGG)
+				ov_pcm_seek(snd->m_pVorbisFile, (HowCountRePlay  * snd->m_uiStreamSize) / (2 * snd->m_iChannelsCount));
 
-			DWORD SizeCountRePlay = PosInBytes - (snd->StreamSize * HowCountRePlay);
+			DWORD SizeCountRePlay = PosInBytes - (snd->m_uiStreamSize * HowCountRePlay);
 
-			ReLoadSplit(id, 0, snd->StreamSize);
+			reLoadSplit(id, 0, snd->m_uiStreamSize);
 
-			snd->RePlayCount = HowCountRePlay;
-			snd->DSBuffer->SetCurrentPosition(SizeCountRePlay);
+			snd->m_iRePlayCount = HowCountRePlay;
+			snd->m_pSoundBuffer->SetCurrentPosition(SizeCountRePlay);
 
 			for (WORD i = 0; i<4; i++)
 			{
-				if (SizeCountRePlay >= snd->Split1Size * i && SizeCountRePlay < snd->Split1Size * (i + 1))
+				if (SizeCountRePlay >= snd->m_uiSplit1Size * i && SizeCountRePlay < snd->m_uiSplit1Size * (i + 1))
 				{
-					snd->SplitActive = i + 1;
+					snd->m_iSplitActive = i + 1;
 					break;
 				}
 			}
 
-			if (snd->SplitActive > 1)
-				snd->IsStarting = false;
+			if (snd->m_iSplitActive > 1)
+				snd->m_isStarting = false;
 			else
-				snd->IsStarting = true;
+				snd->m_isStarting = true;
 
-			if (snd->SplitActive - 2 > 0 && snd->SplitActive - 2 < 5)
+			if (snd->m_iSplitActive - 2 > 0 && snd->m_iSplitActive - 2 < 5)
 			{
-				for (WORD i = 0; i<snd->SplitActive - 2; i++)
-					ReLoadSplit(id, snd->Split1Size*i, snd->Split1Size);
+				for (WORD i = 0; i<snd->m_iSplitActive - 2; i++)
+					reLoadSplit(id, snd->m_uiSplit1Size*i, snd->m_uiSplit1Size);
 			}
 
-			snd->BF1 = snd->BF2 = snd->BF3 = snd->BF4 = false;
+			snd->m_isWork1 = snd->m_isWork2 = snd->m_isWork3 = snd->m_isWork4 = false;
 		}
 		else
-			snd->DSBuffer->SetCurrentPosition(PosInBytes);
+			snd->m_pSoundBuffer->SetCurrentPosition(PosInBytes);
 	}
 }
 
-DWORD MainSound::SoundPosCurrGet(ID id, int type)
+UINT CSoundManager::soundGetPosPlay(ID id)
 {
 	SOUND_PRECOND(id, 0);
 
-	Sound* snd = ArrSounds[id];
-	DWORD posinduff, Bytes, Pos = 0;
-	if (snd->DSBuffer)
+	CSound* snd = m_aSounds[id];
+	DWORD dwPosBuff, dwBytes, dwPos = 0;
+	if (snd->m_pSoundBuffer)
 	{
-		snd->DSBuffer->GetCurrentPosition(&posinduff, 0);
+		snd->m_pSoundBuffer->GetCurrentPosition(&dwPosBuff, 0);
 
-		if (snd->StreamSize)
-			Bytes = snd->RePlayCount * snd->StreamSize + posinduff;
+		if (snd->m_uiStreamSize)
+			dwBytes = snd->m_iRePlayCount * snd->m_uiStreamSize + dwPosBuff;
 		else
-			Bytes = posinduff;
-
-		if (type == SOUND_POS_BYTES)
-			Pos = Bytes;
-		else if (type == SOUND_POS_SEC)
-			Pos = Bytes / snd->BytesPerSec;
-		else if (type == SOUND_POS_MLS)
-			Pos = Bytes / (snd->BytesPerSec / 1000);
+			dwBytes = dwPosBuff;
+
+		dwPos = dwBytes / (snd->m_uiBytesPerSec / 1000);
 	}
-	return Pos;
+	return dwPos;
 }
 
-void MainSound::SoundVolumeSet(ID id, long volume, int type)
+void CSoundManager::soundSetVolume(ID id, float fVolume)
 {
 	SOUND_PRECOND(id, _VOID);
 
-	Sound* snd = ArrSounds[id];
-	if (snd->DSBuffer)
+	CSound *pSnd = m_aSounds[id];
+	pSnd->m_fVolume = saturatef(fVolume);
+
+	if (pSnd->m_pSoundBuffer)
 	{
-		if (type == SOUND_VOL_DB)
-			snd->Volume = volume;
-		else if (type == SOUND_VOL_PCT)
-			snd->Volume = -10000 + (volume * 100);
+		int iVolume = -10000 + (pSnd->m_fVolume * 10000);
 
-		if (!snd->Is3d)
-			snd->DSBuffer->SetVolume(snd->Volume);
+		if (!pSnd->m_is3d)
+			pSnd->m_pSoundBuffer->SetVolume(iVolume);
 	}
 }
 
-long MainSound::SoundVolumeGet(ID id, int type)
+float CSoundManager::soundGetVolume(ID id)
 {
 	SOUND_PRECOND(id, 0);
 
-	Sound* snd = ArrSounds[id];
-	static long volume = 0;
-	if (snd->DSBuffer)
-	{
-		if (type == SOUND_VOL_DB)
-		{
-			if (snd->Is3d)
-				volume = snd->Volume;
-			else
-				snd->DSBuffer->GetVolume(&volume);
-		}
-		else if (type == SOUND_VOL_PCT)
-		{
-			if (snd->Is3d)
-			{
-				double one_percent = 100.0 / (-10000.0);
-				volume = double(snd->Volume) * one_percent;
-			}
-			else
-			{
-				double one_percent = 100.0 / (-10000.0);
-				snd->DSBuffer->GetVolume(&volume);
-				volume = double(volume) * one_percent;
-			}
-		}
-	}
-	return volume;
+	CSound *pSnd = m_aSounds[id];
+	return pSnd->m_fVolume;
 }
 
 
-void MainSound::SoundPanSet(ID id, long value, int type)
+void CSoundManager::soundSetPan(ID id, float fPan)
 {
 	SOUND_PRECOND(id, _VOID);
 
-	Sound* snd = ArrSounds[id];
-	static long Value = 0;
-	if (snd->DSBuffer)
+	CSound *pSnd = m_aSounds[id];
+
+	if (pSnd->m_is3d)
+		return;
+
+	pSnd->m_fPan = clampf(fPan,-1.f,1.f);
+
+	if (pSnd->m_pSoundBuffer)
 	{
-		if (type == SOUND_VOL_DB || value == 0)
-			Value = value;
-		else if (type == SOUND_VOL_PCT && value != 0)
-			Value = (value > 0) ? (10000 - (value * 100)) - 10000 : 10000 - (10000 + (value * 100));
+		long lValue = (pSnd->m_fPan > 0) ? (10000 - (pSnd->m_fPan * 100)) - 10000 : 10000 - (10000 + (pSnd->m_fPan * 100));
 
-		snd->DSBuffer->SetPan(Value);
+		pSnd->m_pSoundBuffer->SetPan(lValue);
 	}
 }
 
-long MainSound::SoundPanGet(ID id, int type)
+float CSoundManager::soundGetPan(ID id)
 {
 	SOUND_PRECOND(id, 0);
 
-	Sound* snd = ArrSounds[id];
-	static long Value = 0;
-	if (snd->DSBuffer)
-	{
-		if (type == SOUND_VOL_DB)
-			snd->DSBuffer->GetPan(&Value);
-		else
-		{
-			double coef_percent = 100.0 / (10000.0);
-			snd->DSBuffer->GetPan(&Value);
-			Value = double(Value) * coef_percent;
-		}
-	}
-	return Value;
+	CSound *pSnd = m_aSounds[id];
+
+	if (pSnd->m_is3d)
+		return 0;
+
+	return pSnd->m_fPan;
 }
 
 
-void MainSound::SoundFreqCurrSet(ID id, DWORD value)
+void CSoundManager::soundSetFreqCurr(ID id, UINT value)
 {
 	SOUND_PRECOND(id, _VOID);
 
-	Sound* snd = ArrSounds[id];
-	if (snd->DSBuffer)
-		snd->DSBuffer->SetFrequency(value);
+	CSound* snd = m_aSounds[id];
+	if (snd->m_pSoundBuffer)
+		snd->m_pSoundBuffer->SetFrequency(value);
 }
 
-DWORD MainSound::SoundFreqCurrGet(ID id)
+UINT CSoundManager::soundGetFreqCurr(ID id)
 {
 	SOUND_PRECOND(id, 0);
 
-	Sound* snd = ArrSounds[id];
+	CSound* snd = m_aSounds[id];
 	static DWORD Value = 0;
-	if (snd->DSBuffer)
-		snd->DSBuffer->GetFrequency(&Value);
+	if (snd->m_pSoundBuffer)
+		snd->m_pSoundBuffer->GetFrequency(&Value);
 	return Value;
 }
 
-DWORD MainSound::SoundFreqOriginGet(ID id)
+UINT CSoundManager::soundGetFreqOrigin(ID id)
 {
 	SOUND_PRECOND(id, 0);
 
-	Sound* snd = ArrSounds[id];
-	if (snd->DSBuffer)
-		return snd->FrecOrigin;
+	CSound* snd = m_aSounds[id];
+	if (snd->m_pSoundBuffer)
+		return snd->m_uiFrecOrigin;
 
 	return 0;
 }
 
-void MainSound::SoundPosWSet(ID id, const float3* pos)
+void CSoundManager::soundSetPosWorld(ID id, const float3* pos)
 {
 	SOUND_PRECOND(id, _VOID);
 	if (pos)
-		ArrSounds[id]->Position = *pos;
+		m_aSounds[id]->m_vPosition = *pos;
 }
 
-void MainSound::SoundPosWGet(ID id, float3* pos)
+void CSoundManager::soundGetPosWorld(ID id, float3* pos)
 {
 	SOUND_PRECOND(id, _VOID);
 	if (pos)
-		*pos = ArrSounds[id]->Position;
+		*pos = m_aSounds[id]->m_vPosition;
 }
 
-int MainSound::SoundLengthSecGet(ID id)
+int CSoundManager::soundGetLengthSec(ID id)
 {
 	SOUND_PRECOND(id, 0);
 
-	return ArrSounds[id]->LengthSec;
+	return m_aSounds[id]->m_iLengthSec;
 }
 
-DWORD MainSound::SoundBytesPerSecGet(ID id)
+UINT CSoundManager::soundGetBytesPerSec(ID id)
 {
 	SOUND_PRECOND(id, 0);
 
-	return ArrSounds[id]->BytesPerSec;
+	return m_aSounds[id]->m_uiBytesPerSec;
 }
 
-DWORD MainSound::SoundSizeGet(ID id)
+UINT CSoundManager::soundGetSize(ID id)
 {
 	SOUND_PRECOND(id, 0);
 
-	return ArrSounds[id]->SizeFull;
+	return m_aSounds[id]->m_uiSizeFull;
 }
 
-void MainSound::SoundFileGet(ID id, char* path)
+void CSoundManager::soundGetFile(ID id, char* path)
 {
 	SOUND_PRECOND(id, _VOID);
 
 	if(path)
-		strcpy(path,ArrSounds[id]->RPath);
+		strcpy(path,m_aSounds[id]->m_szRPath);
 }
 
 
-float MainSound::SoundDistAudibleGet(ID id)
+float CSoundManager::soundGetDistAudible(ID id)
 {
 	SOUND_PRECOND(id, 0);
 
-	return ArrSounds[id]->DistAudible;
+	return m_aSounds[id]->m_fDistAudible;
 }
 
-void MainSound::SoundDistAudibleSet(ID id, float value)
+void CSoundManager::soundSetDistAudible(ID id, float value)
 {
 	SOUND_PRECOND(id, _VOID);
 
-	ArrSounds[id]->DistAudible = value;
+	m_aSounds[id]->m_fDistAudible = value;
 }
 
 //#############################################################################
 
-void MainSound::ReLoadSplit(ID id, DWORD Pos, DWORD Size)
+void CSoundManager::reLoadSplit(ID id, UINT Pos, UINT Size)
 {
 	SOUND_PRECOND(id, _VOID);
 
-	Sound* snd = ArrSounds[id];
-	if (snd->DSBuffer)
+	CSound* snd = m_aSounds[id];
+	if (snd->m_pSoundBuffer)
 	{
 		//wav
-		if (snd->Format == SOUND_FILEFORMAT_WAV)
-			SoundDataWAVLoad(snd->DSBuffer, Pos, snd->StreamFile, Size, 0);
+		if (snd->m_format == SOUND_FILEFORMAT_WAV)
+			soundDataWAVLoad(snd->m_pSoundBuffer, Pos, snd->m_pStream, Size, 0);
 		//ogg
-		else if (snd->Format == SOUND_FILEFORMAT_OGG)
+		else if (snd->m_format == SOUND_FILEFORMAT_OGG)
 		{
-			SoundDataOGGLoad(snd->VorbisFile, snd->DSBuffer, Pos, Size, 0);
+			soundDataOGGLoad(snd->m_pVorbisFile, snd->m_pSoundBuffer, Pos, Size, 0);
+		}
+	}
+}
+
+void CSoundManager::UpdatePlayDelay(CSoundBase *pSndBase)
+{
+	if (!pSndBase)
+		return;
+
+	DWORD dwStatus = 0;
+
+	//если вопроизведение с задержками
+	if (pSndBase->m_isPlayDelay)
+	{
+		if (pSndBase->m_state == SOUND_OBJSTATE_PLAY && pSndBase->m_isLooping && pSndBase->oPlayDelay.m_iCurrPlayDelay == -1 && SUCCEEDED(pSndBase->m_pSoundBuffer->GetStatus(&dwStatus)) && !(dwStatus & DSBSTATUS_PLAYING))
+		{
+			pSndBase->oPlayDelay.m_iCurrPlayDelay = 0;
+			pSndBase->oPlayDelay.m_uiPlayDelayStart = 0;
+			pSndBase->m_pSoundBuffer->SetCurrentPosition(0);
+			pSndBase->m_pSoundBuffer->Play(0, 0, 0);
+		}
+
+		dwStatus = 0;
+
+		DWORD dwCurrPos = 0;
+
+		pSndBase->m_pSoundBuffer->GetCurrentPosition(&dwCurrPos, 0);
+		dwCurrPos = dwCurrPos / (pSndBase->m_uiBytesPerSec / 1000);
+
+		//если текущий ключ в массиве задержек валиден
+		if (pSndBase->oPlayDelay.m_iCurrPlayDelay >= 0 && pSndBase->oPlayDelay.m_aPlayDelay.size() > pSndBase->oPlayDelay.m_iCurrPlayDelay)
+		{
+			if (
+				//если текущий ключ в массиве это не задержка и текущая время воспроизведения больше либо равно установленному
+				(!(pSndBase->oPlayDelay.m_aPlayDelay[pSndBase->oPlayDelay.m_iCurrPlayDelay].m_isDelay) && dwCurrPos >= pSndBase->oPlayDelay.m_aPlayDelay[pSndBase->oPlayDelay.m_iCurrPlayDelay].m_uiTime) ||
+
+				//если текущий ключ в массиве это задержка и время с засечки уже превысило установленное значение либо равно ему
+				(pSndBase->oPlayDelay.m_aPlayDelay[pSndBase->oPlayDelay.m_iCurrPlayDelay].m_isDelay && (GetTickCount() - pSndBase->oPlayDelay.m_uiPlayDelayStart) >= pSndBase->oPlayDelay.m_aPlayDelay[pSndBase->oPlayDelay.m_iCurrPlayDelay].m_uiTime)
+				)
+			{
+				//инкрементируем текущий ключ
+				++(pSndBase->oPlayDelay.m_iCurrPlayDelay);
+
+				//если следующий ключ валиден
+				if (pSndBase->oPlayDelay.m_aPlayDelay.size() > pSndBase->oPlayDelay.m_iCurrPlayDelay)
+				{
+					//если задержка
+					if (pSndBase->oPlayDelay.m_aPlayDelay[pSndBase->oPlayDelay.m_iCurrPlayDelay].m_isDelay)
+					{
+						//естанавливаем и засекаем время
+						pSndBase->m_pSoundBuffer->Stop();
+						pSndBase->oPlayDelay.m_uiPlayDelayStart = GetTickCount();
+					}
+					else
+					{
+						//воспроизводим и обнуляем засечку
+						pSndBase->m_pSoundBuffer->Play(0, 0, 0);
+						pSndBase->oPlayDelay.m_uiPlayDelayStart = 0;
+					}
+				}
+				//иначе ключ в массиве задержек невалиден
+				else
+				{
+					//воспроизводим остаток и обнуляем данные настроек
+					pSndBase->m_pSoundBuffer->Play(0, 0, 0);
+
+					if (!(pSndBase->m_isLooping))
+						pSndBase->m_isPlayDelay = false;
+
+					pSndBase->oPlayDelay.m_iCurrPlayDelay = -1;
+					pSndBase->oPlayDelay.m_uiPlayDelayStart = 0;
+				}
+			}
 		}
 	}
 }
 
-void MainSound::Update(const float3* viewpos, const float3* viewdir)
+void CSoundManager::update(const float3* viewpos, const float3* viewdir)
 {
 	int tmpSoundsPlayCount = 0;
 	int tmpSoundsLoadCount = 0;
 
-	Sound* snd;
-	DWORD status = 0;
-	for(UINT i = 0; i < ArrSounds.size(); ++i)
+	CSound *pSnd = 0;
+	DWORD dwStatus = 0;
+	for(UINT i = 0; i < m_aSounds.size(); ++i)
 	{
-		snd = ArrSounds[i];
-		if(snd)
+		pSnd = m_aSounds[i];
+
+		//если есть звук и его канал вопроизводится
+		if (pSnd && m_aChannels[pSnd->m_idChannel])
 		{
-			status = 0;
-			snd->DSBuffer->GetStatus(&status);
-			if(!(status & DSBSTATUS_PLAYING) && snd->State == SOUND_OBJSTATE_PLAY)
-				SoundStateSet(i, SOUND_OBJSTATE_STOP);
+			//если вопроизведение с задержками
+			if (pSnd->m_state == SOUND_OBJSTATE_PLAY && pSnd->m_uiStreamSize == 0 && pSnd->m_isPlayDelay)
+			{
+				UpdatePlayDelay((CSoundBase*)pSnd);
+			}
+
+			dwStatus = 0;
+			
+			//если звук воспроизводится без задержек и буфер уже не прогирывается а состояние звука "проигрывается" тогда выключаем звук
+			if (!pSnd->m_isPlayDelay && SUCCEEDED(pSnd->m_pSoundBuffer->GetStatus(&dwStatus)) && !(dwStatus & DSBSTATUS_PLAYING) && pSnd->m_state == SOUND_OBJSTATE_PLAY)
+				soundSetState(i, SOUND_OBJSTATE_STOP);
 
 			++tmpSoundsLoadCount;
-			if(snd->State == SOUND_OBJSTATE_PLAY)
+			if(pSnd->m_state == SOUND_OBJSTATE_PLAY)
 				++tmpSoundsPlayCount;
-			if(snd->Is3d && snd->DSBuffer && viewpos && viewdir)
+
+			//если анализируемый звук 3d
+			if(pSnd->m_is3d && pSnd->m_pSoundBuffer && viewpos && viewdir)
 			{
-				snd->DSBuffer->SetVolume(SOUND_3D_COM_VOLUME(snd->Position, (*viewpos), snd->DistAudible));
-				snd->DSBuffer->SetPan(SOUND_3D_COM_PAN(snd->Position, (*viewpos), (*viewdir), snd->DistAudible, snd->ShiftPan));
+				//устанавливаем ему параметры воспроизведения
+				pSnd->m_pSoundBuffer->SetVolume(lerpf(-10000, 0, pSnd->m_fVolume * Snd3dComVolume(pSnd->m_vPosition, (*viewpos), pSnd->m_fDistAudible)));
+				pSnd->m_pSoundBuffer->SetPan(Snd3dComPan(pSnd->m_vPosition, (*viewpos), (*viewdir), pSnd->m_fDistAudible, pSnd->m_fShiftPan));
 
-				if(snd->DataInstances.size() > 0)
+				//если есть инстансы
+				if(pSnd->m_aInstances.size() > 0)
 				{
-					for(int k = 0, l = snd->DataInstances.size(); k < l; ++k)
+					//проходимся по всему массиву инстансов и устанавливаем параметры воспроизведения
+					for(int k = 0, l = pSnd->m_aInstances.size(); k < l; ++k)
 					{
-						snd->DSBuffer->SetVolume(SOUND_3D_COM_VOLUME(snd->DataInstances[k].pos, (*viewpos), snd->DistAudible));
-						snd->DSBuffer->SetPan(SOUND_3D_COM_PAN(snd->DataInstances[k].pos, (*viewpos), (*viewdir), snd->DistAudible, snd->ShiftPan));
+						pSnd->m_pSoundBuffer->SetVolume(lerpf(-10000, 0, pSnd->m_fVolume * Snd3dComVolume(pSnd->m_aInstances[k].m_vPos, (*viewpos), pSnd->m_fDistAudible)));
+						pSnd->m_pSoundBuffer->SetPan(Snd3dComPan(pSnd->m_aInstances[k].m_vPos, (*viewpos), (*viewdir), pSnd->m_fDistAudible, pSnd->m_fShiftPan));
 					}
 				}
 			}
 
-			for(int k = 0, l = snd->DataInstances.size(); k < l; ++k)
+			for(int k = 0, kl = pSnd->m_aInstances.size(); k < kl; ++k)
 			{
-				status = 0;
-				if(SUCCEEDED(snd->DataInstances[k].sbuffer->GetStatus(&status)) && !(status & DSBSTATUS_PLAYING))
-					snd->DataInstances[k].busy = false;
+				//нужно ли это здесь?
+				/*if (pSnd->m_aInstances[k].m_state != SOUND_OBJSTATE_PLAY)
+					continue;*/
+
+				//если вопроизведение с задержками
+				if (pSnd->m_aInstances[k].m_isPlayDelay)
+				{
+					if (pSnd->m_aInstances[k].m_state == SOUND_OBJSTATE_PLAY)
+						UpdatePlayDelay(&(pSnd->m_aInstances[k]));
+				}
+				//иначе не установлено что звук воспроизводится с задержками
+				else
+				{
+					//обрабатываем состояния
+					dwStatus = 0;
+
+					//если буфер не проигрывается и состояние инстанса "временно блокирован", тогда освобождаем инстанс
+					if (SUCCEEDED(pSnd->m_aInstances[k].m_pSoundBuffer->GetStatus(&dwStatus)) && !(dwStatus & DSBSTATUS_PLAYING) && pSnd->m_aInstances[k].m_busy != SOUND_SNDINSTANCE_BUSY_LOCKED)
+						pSnd->m_aInstances[k].m_busy = SOUND_SNDINSTANCE_BUSY_FREE;
+
+					//если буфер инстанса не проигрывается а состояние инстанса "проигрывается", тогда устанавливаем состояние "непроигрывается"
+					if (pSnd->m_aInstances[k].m_state == SOUND_OBJSTATE_PLAY && !(dwStatus & DSBSTATUS_PLAYING))
+						pSnd->m_aInstances[k].m_state = SOUND_OBJSTATE_STOP;
+				}
 			}
 
-			if(snd->StreamSize && snd->DSBuffer != 0)
+			if(pSnd->m_uiStreamSize && pSnd->m_pSoundBuffer != 0)
 			{
 				DWORD pos;
-				snd->DSBuffer->GetCurrentPosition(&pos, 0);
+				pSnd->m_pSoundBuffer->GetCurrentPosition(&pos, 0);
 
-				if(pos >= snd->Split1Size && pos < snd->Split2Size && !snd->BF2)
+				if (pos >= pSnd->m_uiSplit1Size && pos < pSnd->m_uiSplit2Size && !pSnd->m_isWork2)
 				{
-					ReLoadSplit(i, 0, snd->Split1Size);
-					snd->BF2 = true;
-					snd->BF1 = false; snd->BF3 = false; snd->BF4 = false;
-					snd->SplitActive = 2;
+					reLoadSplit(i, 0, pSnd->m_uiSplit1Size);
+					pSnd->m_isWork2 = true;
+					pSnd->m_isWork1 = false; pSnd->m_isWork3 = false; pSnd->m_isWork4 = false;
+					pSnd->m_iSplitActive = 2;
 				}
-				else if(pos >= snd->Split2Size && pos < snd->Split3Size && !snd->BF3)
+				else if (pos >= pSnd->m_uiSplit2Size && pos < pSnd->m_uiSplit3Size && !pSnd->m_isWork3)
 				{
-					snd->BF3 = true;
-					snd->BF1 = false; snd->BF2 = false; snd->BF4 = false;
-					ReLoadSplit(i, snd->Split1Size, snd->Split1Size);
-					snd->SplitActive = 3;
+					pSnd->m_isWork3 = true;
+					pSnd->m_isWork1 = false; pSnd->m_isWork2 = false; pSnd->m_isWork4 = false;
+					reLoadSplit(i, pSnd->m_uiSplit1Size, pSnd->m_uiSplit1Size);
+					pSnd->m_iSplitActive = 3;
 				}
-				else if(pos >= snd->Split3Size && pos < snd->StreamSize && !snd->BF4)
+				else if (pos >= pSnd->m_uiSplit3Size && pos < pSnd->m_uiStreamSize && !pSnd->m_isWork4)
 				{
-					snd->BF4 = true;
-					snd->BF1 = false; snd->BF2 = false; snd->BF3 = false;
-					ReLoadSplit(i, snd->Split2Size, snd->Split1Size);
-					snd->SplitActive = 4;
+					pSnd->m_isWork4 = true;
+					pSnd->m_isWork1 = false; pSnd->m_isWork2 = false; pSnd->m_isWork3 = false;
+					reLoadSplit(i, pSnd->m_uiSplit2Size, pSnd->m_uiSplit1Size);
+					pSnd->m_iSplitActive = 4;
 				}
-				else if(pos < snd->Split1Size && !snd->BF1)
+				else if (pos < pSnd->m_uiSplit1Size && !pSnd->m_isWork1)
 				{
-					snd->BF1 = true;
-					snd->BF2 = false; snd->BF3 = false; snd->BF4 = false;
-					if(!snd->IsStarting)
+					pSnd->m_isWork1 = true;
+					pSnd->m_isWork2 = false; pSnd->m_isWork3 = false; pSnd->m_isWork4 = false;
+					if(!pSnd->m_isStarting)
 					{
-						ReLoadSplit(i, snd->Split3Size, snd->Split1Size);
-						snd->RePlayCount++;
+						reLoadSplit(i, pSnd->m_uiSplit3Size, pSnd->m_uiSplit1Size);
+						pSnd->m_iRePlayCount++;
 					}
-					snd->SplitActive = 1;
-					snd->IsStarting = false;
+					pSnd->m_iSplitActive = 1;
+					pSnd->m_isStarting = false;
 				}
 
 
-				if(snd->RePlayCount + 1 == snd->RePlayEndCount)
+				if(pSnd->m_iRePlayCount + 1 == pSnd->m_iRePlayEndCount)
 				{
-					if(snd->SizeFull <= (snd->StreamSize * snd->RePlayCount + pos))
+					if(pSnd->m_uiSizeFull <= (pSnd->m_uiStreamSize * pSnd->m_iRePlayCount + pos))
 					{
-						if(!snd->IsLooping)
-							SoundStop(i);
+						if(!pSnd->m_isLooping)
+							soundStop(i);
 
 						//wav
-						if(snd->Format == SOUND_FILEFORMAT_WAV)
-							fseek(snd->StreamFile, sizeof(SoundWaveHeader), SEEK_SET);
+						if(pSnd->m_format == SOUND_FILEFORMAT_WAV)
+							fseek(pSnd->m_pStream, sizeof(CSoundWaveHeader), SEEK_SET);
 						//ogg
-						else if(snd->Format == SOUND_FILEFORMAT_OGG)
-							ov_pcm_seek(snd->VorbisFile, 0);
+						else if(pSnd->m_format == SOUND_FILEFORMAT_OGG)
+							ov_pcm_seek(pSnd->m_pVorbisFile, 0);
 
-						ReLoadSplit(i, 0, snd->StreamSize);
+						reLoadSplit(i, 0, pSnd->m_uiStreamSize);
 
-						snd->DSBuffer->SetCurrentPosition(0);
+						pSnd->m_pSoundBuffer->SetCurrentPosition(0);
 
-						snd->RePlayCount = 0;
-						snd->IsStarting = true;
+						pSnd->m_iRePlayCount = 0;
+						pSnd->m_isStarting = true;
 
-						snd->BF1 = false; snd->BF2 = false; snd->BF3 = false; snd->BF4 = false;
+						pSnd->m_isWork1 = false; pSnd->m_isWork2 = false; pSnd->m_isWork3 = false; pSnd->m_isWork4 = false;
 					}
 				}
 			}
 		}
 	}
 
-	SoundsPlayCount = tmpSoundsPlayCount;
-	SoundsLoadCount = tmpSoundsLoadCount;
+	m_iSoundsPlayCount = tmpSoundsPlayCount;
+	m_iSoundsLoadCount = tmpSoundsLoadCount;
 
-	OldViewPos = *viewpos;
-	OldViewDir = *viewdir;
+	m_vOldViewPos = *viewpos;
+	m_vOldViewDir = *viewdir;
 }
 
-int MainSound::SoundsPlayCountGet()
+int CSoundManager::soundsGetPlayCount()
 {
-	return SoundsPlayCount;
+	return m_iSoundsPlayCount;
 }
 
-int MainSound::SoundsLoadCountGet()
+int CSoundManager::soundsGetLoadCount()
 {
-	return SoundsLoadCount;
+	return m_iSoundsLoadCount;
 }
diff --git a/source/score/sound.h b/source/score/sound.h
index a5fe99dde8c8e2cb64cce4c565091fc602ec71fb..b2349a66a4b6648fd913a28a58b12f4a933f1ae9 100644
--- a/source/score/sound.h
+++ b/source/score/sound.h
@@ -1,31 +1,36 @@
-
-/***********************************************************
-Copyright © Vitaliy Buturlin, Evgeny Danilovich, 2017, 2018
-See the license in LICENSE
-***********************************************************/
-
-#ifndef __SOUND_H
-#define __SOUND_H
-
-#pragma comment(lib, "dxguid.lib")
-#pragma comment(lib, "dsound.lib")
-#pragma comment(lib, "libogg_static.lib")
-#pragma comment(lib, "libvorbis_static.lib")
-#pragma comment(lib, "libvorbisfile_static.lib")
-#include <gdefines.h>
-#include <windows.h>
-#include <mmsystem.h>
-#include <dsound.h>
-#include <stdint.h>
-#include <vorbis/codec.h>
-#include <vorbis/vorbisfile.h>
-#include <common/aastring.h>
-#include <common/array.h>
-#include <common/assotiativearray.h>
-#include "sxscore.h"
-
-struct AAStringNR : public AAString
-{
+
+/***********************************************************
+Copyright © Vitaliy Buturlin, Evgeny Danilovich, 2017, 2018
+See the license in LICENSE
+***********************************************************/
+
+#ifndef __SOUND_H
+#define __SOUND_H
+
+#pragma comment(lib, "dxguid.lib")
+#pragma comment(lib, "dsound.lib")
+#pragma comment(lib, "libogg_static.lib")
+#pragma comment(lib, "libvorbis_static.lib")
+#pragma comment(lib, "libvorbisfile_static.lib")
+#include <gdefines.h>
+#include <windows.h>
+#include <mmsystem.h>
+#include <dsound.h>
+#include <stdint.h>
+#include <vorbis/codec.h>
+#include <vorbis/vorbisfile.h>
+#include <common/aastring.h>
+#include <common/array.h>
+#include <common/string.h>
+#include <common/string_func.h>
+#include <common/assotiativearray.h>
+#include "sxscore.h"
+
+//##########################################################################
+
+//перенести в common
+struct AAStringNR : public AAString
+{
 	__forceinline AAStringNR(const char * str)
 	{
 		tmpName = str;
@@ -36,238 +41,613 @@ struct AAStringNR : public AAString
 	{
 		tmpName = NULL;
 		Name[0] = 0;
-	}
-
+	}
+
 	__forceinline bool operator==(const AAStringNR & str) const
 	{
 		return(stricmp(tmpName ? tmpName : Name, str.tmpName ? str.tmpName : str.Name) == 0);
-	}
-};
-
-
-#define SOUND_PRECOND(id, retval) \
-if((UINT)id >= ArrSounds.size() || !(ArrSounds[id]))\
+	}
+};
+
+//##########################################################################
+
+/*! проверка допустимости id звука, в случае провала вылет */
+#define SOUND_PRECOND(id, retval) \
+if (id >= m_aSounds.size() || id < 0 || !(m_aSounds[id]))\
 {LibReport(REPORT_MSG_LEVEL_ERROR, "%s - unresolved address to sound %d", GEN_MSG_LOCATION, id); return retval; }
-
-inline long SOUND_3D_COM_VOLUME(const float3 & snd_pos, const float3 & view_pos, const float snd_distaudible)
-{
-	long vol = (SMVector3Distance(snd_pos, view_pos) / snd_distaudible) * (-10000);
-
-	if (vol > 0)
-		vol = 0;
-
-	if (vol < -10000)
-		vol = -10000;
-
-	return vol;
-}
-
-//чтение файла
-size_t ogg_read(void *ptr, size_t size, size_t nmemb, void *datasource);
-//закртытие файла
-int ogg_close(void* datasource);
-//позиционирование
-int ogg_seek(void *datasource, ogg_int64_t offset, int whence);
-//размер файла
-long ogg_tell(void* datasource);
-
-inline long SOUND_3D_COM_PAN(const float3 & snd_pos, const float3 & view_pos, const float3 & view_dir, const float snd_distaudible, const float snd_shiftpan)
-{
-	float dist = SMVector3Distance(snd_pos, view_pos);
-	float3 vec = view_pos + view_dir;
-
-	float str = (snd_pos.x - view_pos.x)*(snd_pos.z - vec.z) - (snd_pos.z - view_pos.z)*(snd_pos.x - vec.x);
-	return ((str * (dist / snd_distaudible)) * snd_shiftpan * (-10000));
-}
-
-//структура для загрузки wave файла
-struct SoundWaveHeader
-{
-	char	RiffSig[4];
-	int32_t	ChunkSize;
-	char	Sig[4];
-	char	FormatSig[4];
-	int32_t	FormatChunkSize;
-	int16_t	FormatTag;
-	int16_t	Channels;
-	int32_t	SampleRate;
-	int32_t	BytesPerSec;
-	int16_t	BlockAlign;
-	int16_t	BitsPerSample;
-	char	DataSig[4];
-	int32_t	DataSize;
-};
-
-
-class MainSound
-{
-public:
-	MainSound();
-	~MainSound();
-
-	SX_ALIGNED_OP_MEM
-
-	void Clear();
-
-	void Init(HWND hwnd);
-
-	struct Sound
-	{
-		Sound();
-		~Sound();
-		SX_ALIGNED_OP_MEM
-
-		char RPath[SOUND_MAX_SIZE_PATH];
-		ID Id;
-		bool IsInst;
-		FILE* StreamFile;
-		IDirectSoundBuffer8* DSBuffer;	//звуковой буфер
-		OggVorbis_File* VorbisFile;		//поток для декодирования ogg
-
-		struct SIData
-		{
-			SIData(){ sbuffer = 0; busy = false; }
-			SIData(IDirectSoundBuffer8* _sbuffer, float3_t* _pos, bool _busy)
-			{
-				sbuffer = _sbuffer; if (_pos) pos = *_pos; busy = _busy;
-			}
-			~SIData()
-			{
-				mem_release(sbuffer);
-			}
-
-			IDirectSoundBuffer8* sbuffer;
-			float3_t pos;
-			bool busy;
-		};
-
-		Array<SIData> DataInstances;
-
-		SOUND_FILEFORMAT Format;		//формат файла
-		DWORD SizeFull;				//полный размер в байтах (для wav исключая заголовочную структуру)
-		
-		float3 Position;	//позиция источника звука
-		//float Damping;	//сброс громкости при отдалении на метр, т.е. count_volume = volume - dist * Damping %
-		
-		//изменение позиционирования звука, на сколько будет смещен звук при поворотах камеры к источнику звука
-		//чем ближе к объекту тем меньше разница в позиционировании при поворотах
-		float ShiftPan;		
-
-		SOUND_OBJSTATE State;
-		DWORD FrecOrigin;	//оригинальная частота
-
-		float DistAudible;	
-
-		DWORD StreamSize;//размер потока в байтах
-		int LengthSec;
-		int ChannelsCount;
-		int RateSample;
-		int BitsPerSample;
-		DWORD BytesPerSec;
-		long Volume;	
-
-		//размеры сплитов потока
-		DWORD Split1Size;
-		DWORD Split2Size;
-		DWORD Split3Size;
-
-		//заглушки для работы апдейта на каждый сплит в отдельности
-		bool BF1;
-		bool BF2;
-		bool BF3;
-		bool BF4;
-
-		bool IsLooping;		//зацикливать воспроизведние?
-		bool IsStarting;	//воспроизведение только началось? (для потока)
-		bool Is3d;
-
-		short SplitActive;	//активный сплит
-		int RePlayCount;	//сколько раз был полностью перезагружен поток
-		int	RePlayEndCount;	//сколько раз нужно полностью перезагрузить поток чтоб дойти до конца
-	};
-
-	ID SoundCreate2d(const char *file, bool looping = false, DWORD size_stream = 0);
-	ID SoundCreate3d(const char *file, bool looping, DWORD size_stream, float dist, float shift_pan = 0.1f);
-
-	ID SoundCreate2dInst(const char *file, bool looping = false, DWORD size_stream = 0);
-	ID SoundCreate3dInst(const char *file, bool looping, DWORD size_stream, float dist, float shift_pan = 0.1f);
-
-	ID SoundFind2dInst(const char * file);
-	ID SoundFind3dInst(const char * file);
-
-	void SoundInstancePlay2d(ID id, int volume=100, int pan = 0);
-	void SoundInstancePlay3d(ID id, const float3* pos);
-
-	bool SoundIsInit(ID id);
-	void SoundDelete(ID id);
-
-	void SoundPlay(ID id, int looping=-1);	//проиграть
-	void SoundPause(ID id);					//приостановить
-	void SoundStop(ID id);					//остановить
-
-	void SoundStateSet(ID id, SOUND_OBJSTATE state);
-	SOUND_OBJSTATE SoundStateGet(ID id);
-
-	//текащая позиция проигрывания
-	void SoundPosCurrSet(ID id, DWORD pos, int type = SOUND_POS_BYTES);
-	DWORD SoundPosCurrGet(ID id, int type = SOUND_POS_BYTES);
-
-	//громкость
-	void SoundVolumeSet(ID id, long volume, int type = SOUND_VOL_PCT);
-	long SoundVolumeGet(ID id, int type = SOUND_VOL_PCT);
-
-	//позиционирование между динамиками
-	void SoundPanSet(ID id, long value, int type = SOUND_VOL_PCT);
-	long SoundPanGet(ID id, int type = SOUND_VOL_PCT);
-
-	//частота
-	void SoundFreqCurrSet(ID id, DWORD value);
-	DWORD SoundFreqCurrGet(ID id);
-	DWORD SoundFreqOriginGet(ID id);
-
-	void SoundPosWSet(ID id, const float3* pos);
-	void SoundPosWGet(ID id, float3* pos);
-
-	int SoundLengthSecGet(ID id);		//длина в секундах
-	DWORD SoundBytesPerSecGet(ID id);	//байт в секунде
-	DWORD SoundSizeGet(ID id);			//размер в байтах PCM данных
-	void SoundFileGet(ID id, char* path);//путь до звукового файла
-
-	float SoundDistAudibleGet(ID id);
-	void SoundDistAudibleSet(ID id, float value);
-
-	void Update(const float3* viewpos, const float3* viewdir);
-
-	SOUND_FILEFORMAT FileFormat(const char* file);
-
-	int SoundsPlayCountGet();
-	int SoundsLoadCountGet();
-
-private:
-
-	void Load(Sound* snd, const char* fpath, SOUND_FILEFORMAT fmt);
-
-	void LoadWAV(Sound* snd, const char* fpath);
-	void LoadOGG(Sound* snd, const char* fpath);
-	IDirectSoundBuffer8* SoundBufferCreate(SoundWaveHeader* hdr);
-	void SoundDataWAVLoad(IDirectSoundBuffer8* DSBuffer, long LockPos, FILE* data, long Size, DWORD flag = 0);
-	void SoundDataOGGLoad(OggVorbis_File* VorbisFile, IDirectSoundBuffer8 *DSBuffer, long LockPos, long Size, DWORD flag);
-
-	void ReLoadSplit(ID id, DWORD Pos, DWORD Size);
-
-	ID AddSound(Sound* snd);
-
-	Array<Sound*> ArrSounds;	//массив со всеми звуковыми объектами
-	AssotiativeArray<AAStringNR, ID, false, 16> AArr2dInst;
-	AssotiativeArray<AAStringNR, ID, false, 16> AArr3dInst;
-	
-	IDirectSound8* DeviceSound;		//звуковое устройство
-	IDirectSoundBuffer* DSPrimary;	//первичный буфер
-	int SoundsPlayCount;			//количество проигрываемых звуков
-	int SoundsLoadCount;			//количество загруженных звуков (с учетом как проигрывающихся так и простаивающих)
-
-	float3 OldViewPos;
-	float3 OldViewDir;
-};
-
-#endif
+
+/*! создание имени звука (нужно для разделения между каналами */
+#define SOUND_CREATE_NAME(szStr, szFile, idChannel) sprintf(szStr, "%d|%s", idChannel, szFile);
+
+/*! проверка допустимости id канала, в случае провала вылет */
+#define SOUND_CHANNEL_PRECOND(id, retval) \
+if (!(id >= 0 && id < SOUND_CHANNELS_COUNT)) \
+{LibReport(REPORT_MSG_LEVEL_ERROR, "%s - unresolved id channel %d", GEN_MSG_LOCATION, id); return retval; }
+
+/*! проверка проигрываемости канала */
+#define SOUND_CHANNEL_PLAYING(id, retval) \
+if (m_aChannels[id] != 1) \
+{return retval; }
+
+/*! проверка допустимости id набора звуков, в случае провала вылет */
+#define SOUND_SNDKIT_PRECOND(id, retval) \
+if (!(id >= 0 && id < m_aSoundKits.size() && m_aSoundKits[id])) \
+{LibReport(REPORT_MSG_LEVEL_ERROR, "%s - unresolved id sound kit %d", GEN_MSG_LOCATION, id); return retval; }
+
+//##########################################################################
+
+//! просчет громкости звука, пределы [0, 1]
+inline float Snd3dComVolume(
+	const float3 &vSndPos,		//!< позиция звука
+	const float3 &vViewPos,		//!< позиция слушателя
+	const float fDistAudible	//!< дистанция слышимости
+	)
+{
+	float fVolume = 1.f - (SMVector3Distance(vSndPos, vViewPos) / fDistAudible);// *(-10000);
+
+	return saturatef(fVolume);
+}
+
+//! просчет смещения звука между ушами слушателя
+inline int Snd3dComPan(
+	const float3 &vSndPos,		//!< позиция звука
+	const float3 &vViewPos,		//!< позиция слушателя
+	const float3 &vViewDir,		//!< направление взгляда слушателя
+	const float fDistAudible,	//!< дистанция слышимости
+	const float fShiftPan		//!< коэфициент смещения между ушами слушателя
+	)
+{
+	float fDist = SMVector3Distance(vSndPos, vViewPos);
+	float3 fVec = vViewPos + vViewDir;
+
+	float str = (vSndPos.x - vViewPos.x)*(vSndPos.z - fVec.z) - (vSndPos.z - vViewPos.z)*(vSndPos.x - fVec.x);
+	return ((str * (fDist / fDistAudible)) * fShiftPan * float(-10000));
+}
+
+//! парсинг строки szSrcStr на составляющие элементы (если есть): путь до звука и параметры воспроизведения
+inline bool SndGetDataFromStr(const char *szSrcStr, String &sFile, float &fDistAudible, float &fVolume, Array<UINT> &aDelays)
+{
+	bool existsData = false;
+
+	Array<String> aStrConfig = StrExplode(szSrcStr, " ", false);
+
+	if (aStrConfig[0].length() == 0)
+	{
+		LibReport(REPORT_MSG_LEVEL_ERROR, "%s - invalid file", GEN_MSG_LOCATION);
+		return false;
+	}
+
+	sFile = StrTrim(aStrConfig[0].c_str());
+
+	if (aStrConfig.size() >= 2)
+	{
+		if (aStrConfig[1][0] == 'd' || aStrConfig[1][0] == 'v')
+			existsData = true;
+
+		if (aStrConfig[1][0] == 'd')
+			sscanf(aStrConfig[1].c_str() + 1, "%f", &fDistAudible);
+		else if (aStrConfig[1][0] == 'v')
+			sscanf(aStrConfig[1].c_str() + 1, "%f", &fVolume);
+	}
+
+	if (aStrConfig.size() >= 3)
+	{
+		if (aStrConfig[2][0] == 'd' && fDistAudible > -2.f)
+		{
+			LibReport(REPORT_MSG_LEVEL_ERROR, "%s - unresolved double instruction for 'distance of audibility'", GEN_MSG_LOCATION);
+			return false;
+		}
+
+		if (aStrConfig[2][0] == 'v' && fVolume > -2.f)
+		{
+			LibReport(REPORT_MSG_LEVEL_ERROR, "%s - unresolved double instruction for 'volume'", GEN_MSG_LOCATION);
+			return false;
+		}
+
+		if (aStrConfig[2][0] == 'd' || aStrConfig[2][0] == 'v')
+			existsData = true;
+
+		if (aStrConfig[2][0] == 'd')
+			sscanf(aStrConfig[2].c_str() + 1, "%f", &fDistAudible);
+		else if (aStrConfig[2][0] == 'v')
+			sscanf(aStrConfig[2].c_str() + 1, "%f", &fVolume);
+	}
+
+	for (int k = 3, kl = aStrConfig.size(); k < kl; ++k)
+	{
+		String str = aStrConfig[k];
+		aDelays.push_back(aStrConfig[k].ToUnsLongInt());
+	}
+
+	if (aDelays.size() > 0)
+		existsData = true;
+
+	return existsData;
+}
+
+//##########################################################################
+
+/*! \name Обработчики ogg
+@{*/
+
+//! чтение файла
+size_t OggCallbackRead(void *ptr, size_t size, size_t nmemb, void *datasource);
+
+//! закртытие файла
+int OggCallbackClose(void* datasource);
+
+//! позиционирование
+int OggCallbackSeek(void *datasource, ogg_int64_t offset, int whence);
+
+//! размер файла
+long OggCallbackTell(void* datasource);
+
+//!@}
+
+//##########################################################################
+
+//структура для загрузки wave файла
+struct CSoundWaveHeader
+{
+	char	RiffSig[4];
+	int32_t	ChunkSize;
+	char	Sig[4];
+	char	FormatSig[4];
+	int32_t	FormatChunkSize;
+	int16_t	FormatTag;
+	int16_t	Channels;
+	int32_t	SampleRate;
+	int32_t	BytesPerSec;
+	int16_t	BlockAlign;
+	int16_t	BitsPerSample;
+	char	DataSig[4];
+	int32_t	DataSize;
+};
+
+//##########################################################################
+
+//! менеджер звуков
+class CSoundManager
+{
+public:
+	CSoundManager();
+	~CSoundManager();
+
+	SX_ALIGNED_OP_MEM
+
+	void clear();
+
+	void init(HWND hWnd);
+
+	//! структура данных для воспроизведения с задержками
+	struct CPlayDelay
+	{
+		CPlayDelay()
+		{
+			m_iCurrPlayDelay = 0;
+			m_uiPlayDelayStart = 0;
+		}
+
+		//! структура для хранения данных о текущей настройке проигрывания
+		struct CTimeDelay
+		{
+			CTimeDelay(){ m_uiTime = 0; m_isDelay = false; }
+			CTimeDelay(UINT uiTime, bool isDelay)
+			{
+				m_uiTime = uiTime; m_isDelay = isDelay;
+			}
+
+			//! время в млсек
+			UINT m_uiTime;
+
+			//! это время задержки в проигрывании или нет?
+			bool m_isDelay;
+		};
+
+		//! массив настроек прогирывания
+		Array<CTimeDelay> m_aPlayDelay;
+
+		//! текущий индекс в #m_aPlayDelay
+		int m_iCurrPlayDelay;
+
+		//! стартовое время задержки в млсек (если засекали время)
+		UINT m_uiPlayDelayStart;
+
+	};
+
+	//! структура данных базового понятия звука
+	struct CSoundBase
+	{
+		CSoundBase()
+		{ 
+			m_pSoundBuffer = 0; m_state = SOUND_OBJSTATE_STOP; m_isLooping = false; m_isPlayDelay = false; m_uiBytesPerSec = 0; m_fVolume = 1.f; m_fPan = 0;
+		}
+
+		~CSoundBase()
+		{
+			mem_release(m_pSoundBuffer);
+		}
+
+		//! звуковой буфер инстанса
+		IDirectSoundBuffer8 *m_pSoundBuffer;
+
+		//! количество байт в секунде
+		UINT m_uiBytesPerSec;
+
+		//! состояние воспроизведения
+		SOUND_OBJSTATE m_state;
+
+		//! зацикливать ли воспроизведение
+		bool m_isLooping;
+
+		//! используется ли воспроизведение с задержками
+		bool m_isPlayDelay;
+
+		//! объект с данными проигрывания
+		CPlayDelay oPlayDelay;
+
+		//! громкость [0, 1]
+		float m_fVolume;
+
+		//! смещение между ушами слушателя [-1, 1]
+		float m_fPan;
+	};
+
+	//! структура данных инстанса звука
+	struct CSoundInstance : public CSoundBase
+	{
+		CSoundInstance(){ m_pSoundBuffer = 0; m_uiBytesPerSec = 0; m_busy = SOUND_SNDINSTANCE_BUSY_FREE; m_state = SOUND_OBJSTATE_STOP; m_isPlayDelay = false; }
+		CSoundInstance(IDirectSoundBuffer8 *pBuffer, UINT uiBytesPerSec, const float3_t *vPos, SOUND_SNDINSTANCE_BUSY busy)
+		{
+			m_pSoundBuffer = pBuffer; 
+			m_uiBytesPerSec = uiBytesPerSec;
+			if (vPos) 
+				m_vPos = *vPos; 
+			m_busy = busy;
+			m_state = SOUND_OBJSTATE_STOP;
+			m_isPlayDelay = false;
+		}
+
+		//! позиция воспроизведения (если надо)
+		float3_t m_vPos;
+
+		//! занят ли инстанс в данный момент #SOUND_SNDINSTANCE_BUSY
+		SOUND_SNDINSTANCE_BUSY m_busy;
+	};
+
+	//! расширенное понятие звука
+	struct CSound : public CSoundBase
+	{
+		CSound();
+		~CSound();
+		SX_ALIGNED_OP_MEM
+
+		//! путь загруженного звука
+		char m_szRPath[SOUND_MAX_SIZE_PATH];
+
+		//! идентификатор (номер в общем массиве звуков)
+		ID m_id;
+
+		//! канал
+		ID m_idChannel;
+
+		//! 3д воспроизвдеение звука?
+		bool m_is3d;
+
+		/*! количество загрузок звука, в основном сделано для инстансовых, если один и тот же звук загружался несколько раз то он будет загружен единожды, но счетчик будет показывать колиество,
+		 и звук удалиться только тогда когда последний объект его удалит
+		*/
+		int m_iCountLoad;
+
+		//! изменение позиционирования звука, на сколько будет смещен звук при поворотах камеры к источнику звука, чем ближе к объекту тем меньше разница в позиционировании при поворотах
+		float m_fShiftPan;
+
+		//! дистанция слышимости
+		float m_fDistAudible;
+
+		//! разрешено ли создавать инстансы звука (false по дефолту)
+		bool m_isInst;
+
+		//! потом чтения файла
+		FILE *m_pStream;
+
+		//! поток для декодирования ogg
+		OggVorbis_File *m_pVorbisFile;		
+
+		//! массив инстансов
+		Array<CSoundInstance> m_aInstances;
+
+		//! формат файла
+		SOUND_FILEFORMAT m_format;		
+
+		//! полный размер в байтах (для wav исключая заголовочную структуру)
+		UINT m_uiSizeFull;				
+		
+		//! позиция источника звука (если используется без инстансов, хотя устанавливается главному и при инстансах)
+		float3 m_vPosition;	
+
+		//сброс громкости при отдалении на метр, т.е. count_volume = volume - dist * Damping %
+		//float Damping;	
+
+		//! оригинальная частота
+		UINT m_uiFrecOrigin;	
+
+		//! размер потока в байтах
+		UINT m_uiStreamSize;
+
+		//! длина звука в секундах
+		int m_iLengthSec;
+
+		//! количество каналов
+		int m_iChannelsCount;
+
+		//! частота дискретизации
+		int m_iSampleRate;
+
+		//! количество бит в сэмпле
+		int m_iBitsPerSample;
+
+		//размеры сплитов потока
+		UINT m_uiSplit1Size;
+		UINT m_uiSplit2Size;
+		UINT m_uiSplit3Size;
+
+		//заглушки для работы апдейта на каждый сплит в отдельности
+		bool m_isWork1;
+		bool m_isWork2;
+		bool m_isWork3;
+		bool m_isWork4;
+
+		//! воспроизведение только началось? (для потока)
+		bool m_isStarting;
+
+		//! номер текущего активного сплита
+		int m_iSplitActive;	
+
+		//! сколько раз был полностью перезагружен поток
+		int m_iRePlayCount;	
+
+		//! сколько раз нужно полностью перезагрузить поток чтоб дойти до конца
+		int	m_iRePlayEndCount;
+	};
+
+	//**********************************************************************
+
+	//! набор звуков, для случайного воспроизведения звуков из массива однотипных звуков
+	struct СSoundKit
+	{
+		СSoundKit();
+		~СSoundKit();
+		
+		//! имя набора
+		char m_szName[SOUND_MAX_SIZE_SNDKIT_NAME];
+
+		//! объект набора
+		struct CSoundKitObject
+		{
+			//! идентификатор звука
+			ID m_id;
+
+			//! массив задержек
+			Array<UINT> m_aDelays;
+
+			//! громкость звука [0,1]
+			float m_fVolume;
+		};
+
+		//! массив звуков
+		Array<CSoundKitObject> m_aSounds;
+
+		//! канал набора звуков
+		ID m_idChannel;
+
+		//! 3d (true) или 2d (false) набор?
+		bool m_is3D;
+
+		//! общая дистанция слышимости для 3д звуков
+		float m_fDistAudible;
+	};
+
+	//! создать набор
+	ID sndkitCreate(const char *szName, ID idChannel, bool is3D, float fDistAudible = SOUND_DIST_AUDIBLE_DEFAULT);
+
+	ID sndkitCreateFromList(const char *szName, ID idChannel, Array<String> aStrings, bool is3D, float fDistAudible = SOUND_DIST_AUDIBLE_DEFAULT, float fVolume = 1.f);
+
+	//! добавить звук в набор, если fDistAudible < 0 то будут задействованы настройки самого набора
+	void sndkitAddSound(ID idSndKit, const char *szFile, float fDistAudible, float fVolume = 1.f, UINT *pArrDelay = 0, int iSizeArrDelay = 0);
+
+	//! получить id по имени набора
+	ID sndkitGetID(const char *szName);
+
+	//! получить номер канала
+	ID sndkitGetChannel(ID idSndKit);
+
+	//! получить имя по id набора
+	void sndkitGetName(ID idSndKit, char *szName);
+
+	//! удалить набор
+	void sndkitDelete(ID idSndKit);
+
+	//! удалить все наборы
+	void sndkitDeleteAll();
+
+	/*! проиграть случайный звук
+	 \note если набор 3д звуков, то позиция обязательна
+	 \note id2 должен принимать либо #SOUND_SNDKIT_INSTANCE_BLOCK либо #SOUND_SNDKIT_INSTANCE_NOTBLOCK либо должен быть упакованным значением идентификаторов заблокированного инстанса звука
+	  если инстанс воспроизводимого звука заблокирован, то он не будет использоваться другими пока владелец его не разблокирует
+	 \return возвращает упакованные значения порядкового номера звука (в массиве набора) в 32 старших битах и id инстанса звука в 32 младших битах
+	*/
+	uint64_t sndkitPlay(ID idSndKit, uint64_t id2, const float3 *pPos = 0, float fVolume = -1.f, float fPan = 0.f);
+
+	//! остановить проигрывание звуков в наборе
+	void sndkitStop(ID idSndKit, uint64_t id2);
+
+	//**********************************************************************
+
+	//! добавить канал
+	void channelAdd(ID idChannel, bool isPlaying = false);
+
+	//! существует ил канал
+	bool channelExists(ID idChannel);
+
+	//! количество звуков в канале
+	int channelGetSndCount(ID idChannel);
+
+	//! проигрывать звуки канала
+	void channelPlay(ID idChannel);
+
+	//! проигрывается ли канал?
+	bool channelPlaying(ID idChannel);
+
+	//! остановить проигрывание звуков канала
+	void channelStop(ID idChannel);
+
+	//! проигрывать звуки только этого канала
+	void channelPlayOnly(ID idChannel);
+
+	//! воспроизвести звук канала (используется внутри функций каналов для воспроизведения каналов)
+	void channelSndPlay(ID idChannel, ID idSound);
+
+	//! остановить звук канала (используется внутри функций каналов для воспроизведения каналов)
+	void channelSndStop(ID idChannel, ID idSound);
+
+	//**********************************************************************
+
+	ID soundCreate2d(const char *szFile, ID idChannel, UINT uiSizeStream = 0);
+	ID soundCreate3d(const char *szFile, ID idChannel, UINT uiSizeStream, float fDist);
+
+	ID soundCreate2dInst(const char *szFile, ID idChannel);
+	ID soundCreate3dInst(const char *szFile, ID idChannel, float fDist);
+
+	ID soundFind2dInst(const char *szFile, ID idChannel);
+	ID soundFind3dInst(const char *szFile, ID idChannel);
+
+	/*! воспроизведение инстанса звука, если нужны задержки то надо их указывать в pArrDelay и iSizeArrDelay, иначе в обоих 0, 
+	если нужен 3д звук (если это на самом деле 3д звук) то надо указать pPos, иначе 0 и будет 2д, для 2д по желанию можно указать громкость iVolume и смещение между ушами iPan
+	*/
+	ID soundInstancePlay(ID idSound, bool isBlocked, bool isLooping, UINT *pArrDelay, int iSizeArrDelay, const float3 *pPos, float fVolume = 1.f, float fPan = 0.f);
+
+	bool soundInstancePlaying(ID idSound, ID idInstance);
+	void soundInstanceStop(ID idSound, ID idInstance);
+	void soundInstanceFree(ID idSound, ID idInstance);
+
+	bool soundIsInit(ID idSound);
+	void soundDelete(ID idSound);
+
+	//! проиграть
+	void soundPlay(ID idSound, bool isLooping = false, UINT *pArrDelay = 0, int iSizeArrDelay = 0);
+
+	//! инициализация масисва задержек для воспроизведения звука, если указать iSizeArrDelay = -1 тогда будут задействованы прошлые настройки
+	void soundInitPlayDelay(CSoundBase *pSndbase, UINT *pArrDelay, int iSizeArrDelay);
+
+	//! продолжить воспроизведение (с задержками) остановленного звука
+	void soundResumePlayDelay(CSoundBase *pSndBase);
+
+	//! приостановить
+	void soundPause(ID idSound);
+
+	//! остановить
+	void soundStop(ID idSound);
+
+	void soundSetState(ID idSound, SOUND_OBJSTATE state);
+	SOUND_OBJSTATE soundGetState(ID idSound);
+
+	//текащая позиция проигрывания
+	void soundSetPosPlay(ID idSound, UINT uiPos);
+	UINT soundGetPosPlay(ID idSound);
+
+	//громкость
+	void soundSetVolume(ID idSound, float fVolume);
+	float soundGetVolume(ID idSound);
+
+	//позиционирование между динамиками
+	void soundSetPan(ID idSound, float fPan);
+	float soundGetPan(ID idSound);
+
+	//частота
+	void soundSetFreqCurr(ID idSound, UINT uiFrec);
+	UINT soundGetFreqCurr(ID idSound);
+	UINT soundGetFreqOrigin(ID idSound);
+
+	void soundSetPosWorld(ID idSound, const float3 *pPos);
+	void soundGetPosWorld(ID idSound, float3 *pPos);
+
+
+	//длина в секундах
+	int soundGetLengthSec(ID idSound);
+
+	//байт в секунде
+	UINT soundGetBytesPerSec(ID idSound);
+
+	//размер в байтах PCM данных
+	UINT soundGetSize(ID idSound);
+
+	//путь до звукового файла
+	void soundGetFile(ID idSound, char *szPath);
+
+	float soundGetDistAudible(ID idSound);
+	void soundSetDistAudible(ID idSound, float fDistAudible);
+
+	void UpdatePlayDelay(CSoundBase *pSndBase);
+
+	void update(const float3 *pViewPos, const float3 *pViewDir);
+
+	SOUND_FILEFORMAT fileFormat(const char *szFile);
+
+	int soundsGetPlayCount();
+	int soundsGetLoadCount();
+
+private:
+
+	void load(CSound *pSnd, const char *szPath, SOUND_FILEFORMAT fmt);
+
+	void loadWAV(CSound *pSnd, const char *szPath);
+
+	void loadOGG(CSound *pSnd, const char *szPath);
+
+	IDirectSoundBuffer8* soundBufferCreate(CSoundWaveHeader *pHeader);
+
+	void soundDataWAVLoad(IDirectSoundBuffer8 *pBuffer, int iLockPos, FILE *pData, int iSize, UINT uiFlag = 0);
+	void soundDataOGGLoad(OggVorbis_File *pVorbisFile, IDirectSoundBuffer8 *pBuffer, int iLockPos, int iSize, UINT uiFlag);
+
+	void reLoadSplit(ID id, UINT Pos, UINT Size);
+
+	ID addSound(CSound *pSnd);
+
+	//**********************************************************************
+
+	//! массив со всеми звуковыми объектами
+	Array<CSound*> m_aSounds;
+
+	//! ассоциативный массив всех 2д звуков arr[name] = id;
+	AssotiativeArray<AAStringNR, ID, false, 16> m_a2dInst;
+
+	//! ассоциативный массив всех 3д звуков arr[name] = id;
+	AssotiativeArray<AAStringNR, ID, false, 16> m_a3dInst;
+
+	//! массив наборов звуков
+	Array<СSoundKit*> m_aSoundKits;
+
+	//! массив каналов
+	int m_aChannels[SOUND_CHANNELS_COUNT];
+	
+	//! звуковое устройство
+	IDirectSound8 *m_pDeviceSound;		
+
+	//! первичный буфер
+	IDirectSoundBuffer *m_pPrimaryBuffer;	
+
+	//! количество проигрываемых звуков
+	int m_iSoundsPlayCount;
+
+	//! количество загруженных звуков (с учетом как проигрывающихся так и простаивающих)
+	int m_iSoundsLoadCount;
+
+	//! предыдущая позиция наблюдателя
+	float3 m_vOldViewPos;
+
+	//! предыдущее направление взгляда наблюдателя
+	float3 m_vOldViewDir;
+};
+
+#endif
diff --git a/source/score/sxscore.cpp b/source/score/sxscore.cpp
index 31197743bc4f962a26158c20ad0dba38b8edc33e..6c8842c988aec793bb28de2a00a4953618d43ab7 100644
--- a/source/score/sxscore.cpp
+++ b/source/score/sxscore.cpp
@@ -14,7 +14,7 @@ See the license in LICENSE
 report_func g_fnReportf = DefReport;
 #endif
 
-MainSound *g_pManagerSound = 0;
+CSoundManager *g_pManagerSound = 0;
 
 #define SCORE_PRECOND(retval) if(!g_pManagerSound){LibReport(-1, "%s - sxsound is not init", GEN_MSG_LOCATION); return retval;}
 
@@ -44,14 +44,14 @@ SX_LIB_API void SSCore_0Create(const char *szName, HWND hWnd, bool isUnic)
 			}
 			else
 			{
-				g_pManagerSound = new MainSound();
-				g_pManagerSound->Init(hWnd);
+				g_pManagerSound = new CSoundManager();
+				g_pManagerSound->init(hWnd);
 			}
 		}
 		else
 		{
-			g_pManagerSound = new MainSound();
-			g_pManagerSound->Init(hWnd);
+			g_pManagerSound = new CSoundManager();
+			g_pManagerSound->init(hWnd);
 		}
 	}
 	else
@@ -69,7 +69,7 @@ SX_LIB_API void SSCore_Clear()
 {
 	SCORE_PRECOND(_VOID);
 
-	g_pManagerSound->Clear();
+	g_pManagerSound->clear();
 }
 
 
@@ -77,77 +77,174 @@ SX_LIB_API void SSCore_Update(const float3 *pViewPos, const float3 *pViewDir)
 {
 	SCORE_PRECOND(_VOID);
 
-	g_pManagerSound->Update(pViewPos, pViewDir);
+	g_pManagerSound->update(pViewPos, pViewDir);
 }
 
-SX_LIB_API int SSCore_SndsPlayCountGet()
+SX_LIB_API int SSCore_SndsGetCountPlay()
 {
 	SCORE_PRECOND(0);
 
-	return g_pManagerSound->SoundsPlayCountGet();
+	return g_pManagerSound->soundsGetPlayCount();
 }
 
-SX_LIB_API int SSCore_SndsLoadCountGet()
+SX_LIB_API int SSCore_SndsGetCountLoad()
 {
 	SCORE_PRECOND(0);
 
-	return g_pManagerSound->SoundsLoadCountGet();
+	return g_pManagerSound->soundsGetLoadCount();
 }
 
-SX_LIB_API ID SSCore_SndCreate2d(const char *szFile, bool isLooping, UINT uiSizeStream)
+//##########################################################################
+
+SX_LIB_API void SSCore_ChannelAdd(ID idChannel, bool isPlaying)
+{
+	SCORE_PRECOND(_VOID);
+
+	g_pManagerSound->channelAdd(idChannel, isPlaying);
+}
+
+SX_LIB_API bool SSCore_ChannelExists(ID idChannel)
+{
+	SCORE_PRECOND(false);
+
+	return g_pManagerSound->channelExists(idChannel);
+}
+
+SX_LIB_API int SSCore_ChannelGetSndCount(ID idChannel)
 {
 	SCORE_PRECOND(-1);
 
-	return g_pManagerSound->SoundCreate2d(szFile, isLooping, uiSizeStream);
+	return g_pManagerSound->channelGetSndCount(idChannel);
 }
 
-SX_LIB_API ID SSCore_SndCreate3d(const char *szFile, bool isLooping, UINT uiSizeStream, float fDist, float fShiftPan)
+SX_LIB_API void SSCore_ChannelPlay(ID idChannel)
+{
+	SCORE_PRECOND(_VOID);
+
+	g_pManagerSound->channelPlay(idChannel);
+}
+
+SX_LIB_API void SSCore_ChannelPlayOnly(ID idChannel)
+{
+	SCORE_PRECOND(_VOID);
+
+	g_pManagerSound->channelPlayOnly(idChannel);
+}
+
+SX_LIB_API bool SSCore_ChannelPlaying(ID idChannel)
+{
+	SCORE_PRECOND(false);
+
+	return g_pManagerSound->channelPlaying(idChannel);
+}
+
+SX_LIB_API void SSCore_ChannelStop(ID idChannel)
+{
+	SCORE_PRECOND(_VOID);
+
+	g_pManagerSound->channelStop(idChannel);
+}
+
+//##########################################################################
+
+SX_LIB_API ID SSCore_SndCreate2d(const char *szFile, ID idChannel, UINT uiSizeStream)
 {
 	SCORE_PRECOND(-1);
 
-	return g_pManagerSound->SoundCreate3d(szFile, isLooping, uiSizeStream, fDist, fShiftPan);
+	return g_pManagerSound->soundCreate2d(szFile, idChannel, uiSizeStream);
 }
 
-SX_LIB_API ID SSCore_SndCreate2dInst(const char *szFile, bool isLooping, UINT uiSizeStream)
+SX_LIB_API ID SSCore_SndCreate3d(const char *szFile, ID idChannel, UINT uiSizeStream, float fDist)
 {
 	SCORE_PRECOND(-1);
 
-	return  g_pManagerSound->SoundCreate2dInst(szFile, isLooping, uiSizeStream);
+	return g_pManagerSound->soundCreate3d(szFile, idChannel, uiSizeStream, fDist);
 }
 
-SX_LIB_API ID SSCore_SndCreate3dInst(const char *szFile, bool isLooping, UINT uiSizeStream, float fDist, float fShiftPan)
+SX_LIB_API ID SSCore_SndCreate2dInst(const char *szFile, ID idChannel)
 {
 	SCORE_PRECOND(-1);
 
-	return  g_pManagerSound->SoundCreate3dInst(szFile, isLooping, uiSizeStream, fDist, fShiftPan);
+	return  g_pManagerSound->soundCreate2dInst(szFile, idChannel);
 }
 
-SX_LIB_API ID SSCore_SndFind2dInst(const char *szFile)
+SX_LIB_API ID SSCore_SndCreate3dInst(const char *szFile, ID idChannel, float fDist)
 {
 	SCORE_PRECOND(-1);
 
-	return g_pManagerSound->SoundFind2dInst(szFile);
+	return  g_pManagerSound->soundCreate3dInst(szFile, idChannel, fDist);
 }
 
-SX_LIB_API ID SSCore_SndFind3dInst(const char *szFile)
+SX_LIB_API ID SSCore_SndFind2dInst(const char *szFile, ID idChannel)
 {
 	SCORE_PRECOND(-1);
 
-	return g_pManagerSound->SoundFind3dInst(szFile);
+	return g_pManagerSound->soundFind2dInst(szFile, idChannel);
+}
+
+SX_LIB_API ID SSCore_SndFind3dInst(const char *szFile, ID idChannel)
+{
+	SCORE_PRECOND(-1);
+
+	return g_pManagerSound->soundFind3dInst(szFile, idChannel);
+}
+
+
+SX_LIB_API ID SSCore_SndInstancePlay(ID idSound, bool isBlocked, bool isLooping, UINT *pArrDelay, int iSizeArrDelay, const float3 *pPos, float fVolume, float fPan)
+{
+	SCORE_PRECOND(-1);
+
+	return g_pManagerSound->soundInstancePlay(idSound, isBlocked, isLooping, pArrDelay, iSizeArrDelay, pPos, fVolume, fPan);
+}
+
+/*SX_LIB_API ID SSCore_SndInstancePlay2d(ID idSound, bool isBlocked, bool isLooping, int iVolume, int iPan)
+{
+	SCORE_PRECOND(-1);
+
+	return g_pManagerSound->soundInstancePlay(idSound, isBlocked, isLooping, 0, 0, 0, iVolume, iPan);
+}
+
+SX_LIB_API ID SSCore_SndInstancePlayDelay2d(ID idSound, bool isBlocked, bool isLooping, UINT *pArrDelay, int iSizeArrDelay, int iVolume, int iPan)
+{
+	SCORE_PRECOND(-1);
+
+	return g_pManagerSound->soundInstancePlay(idSound, isBlocked, isLooping, pArrDelay, iSizeArrDelay, 0, iVolume, iPan);
+}
+
+SX_LIB_API ID SSCore_SndInstancePlay3d(ID idSound, bool isBlocked, bool isLooping, const float3 *pPos)
+{
+	SCORE_PRECOND(-1);
+
+	return g_pManagerSound->soundInstancePlay(idSound, isBlocked, isLooping, 0, 0, pPos);
+}
+
+SX_LIB_API ID SSCore_SndInstancePlayDelay3d(ID idSound, bool isBlocked, bool isLooping, UINT *pArrDelay, int iSizeArrDelay, const float3 *pPos)
+{
+	SCORE_PRECOND(-1);
+
+	return g_pManagerSound->soundInstancePlay(idSound, isBlocked, isLooping, pArrDelay, iSizeArrDelay, pPos);
+}*/
+
+
+SX_LIB_API bool SSCore_SndInstancePlaying(ID idSound, ID idInstance)
+{
+	SCORE_PRECOND(false);
+
+	return g_pManagerSound->soundInstancePlaying(idSound, idInstance);
 }
 
-SX_LIB_API void SSCore_SndInstancePlay2d(ID idSound, int iVolume, int iPan)
+SX_LIB_API void SSCore_SndInstanceStop(ID idSound, ID idInstance)
 {
 	SCORE_PRECOND(_VOID);
 
-	g_pManagerSound->SoundInstancePlay2d(idSound, iVolume, iPan);
+	g_pManagerSound->soundInstanceStop(idSound, idInstance);
 }
 
-SX_LIB_API void SSCore_SndInstancePlay3d(ID idSound, const float3 *pPos)
+SX_LIB_API void SSCore_SndInstanceFree(ID idSound, ID idInstance)
 {
 	SCORE_PRECOND(_VOID);
 
-	g_pManagerSound->SoundInstancePlay3d(idSound, pPos);
+	g_pManagerSound->soundInstanceStop(idSound, idInstance);
 }
 
 
@@ -155,173 +252,290 @@ SX_LIB_API bool SSCore_SndIsInit(ID idSound)
 {
 	SCORE_PRECOND(false);
 
-	return g_pManagerSound->SoundIsInit(idSound);
+	return g_pManagerSound->soundIsInit(idSound);
 }
 
 SX_LIB_API void SSCore_SndDelete(ID idSound)
 {
 	SCORE_PRECOND(_VOID);
 
-	g_pManagerSound->SoundDelete(idSound);
+	g_pManagerSound->soundDelete(idSound);
 }
 
 
-SX_LIB_API void SSCore_SndPlay(ID idSound, int isLooping)
+SX_LIB_API void SSCore_SndPlay(ID idSound, bool isLooping, UINT *pArrDelay, int iSizeArrDelay)
 {
 	SCORE_PRECOND(_VOID);
 
-	g_pManagerSound->SoundPlay(idSound, isLooping);
+	g_pManagerSound->soundPlay(idSound, isLooping, pArrDelay, iSizeArrDelay);
 }
 
+/*SX_LIB_API void SSCore_SndPlayDelay(ID idSound, bool isLooping, UINT *pArrDelay, int iSizeArrDelay)
+{
+	SCORE_PRECOND(_VOID);*/
+
+	/*Array<UINT> aValues;
+	
+	UINT uiCurrVal = 0;
+	va_list va;
+	va_start(va, isLooping);
+
+	uiCurrVal = va_arg(va, UINT);
+	while (uiCurrVal > 0)
+	{
+		aValues.push_back(uiCurrVal);
+		uiCurrVal = va_arg(va, UINT);
+	}
+
+	va_end(va);*/
+
+	/*g_pManagerSound->soundPlayDelay(idSound, isLooping, pArrDelay, iSizeArrDelay);
+}*/
+
 SX_LIB_API void SSCore_SndPause(ID idSound)
 {
 	SCORE_PRECOND(_VOID);
 
-	g_pManagerSound->SoundPause(idSound);
+	g_pManagerSound->soundPause(idSound);
 }
 
 SX_LIB_API void SSCore_SndStop(ID idSound)
 {
 	SCORE_PRECOND(_VOID);
 
-	g_pManagerSound->SoundStop(idSound);
+	g_pManagerSound->soundStop(idSound);
 }
 
 
-SX_LIB_API void SSCore_SndStateSet(ID idSound, SOUND_OBJSTATE state)
+SX_LIB_API void SSCore_SndSetState(ID idSound, SOUND_OBJSTATE state)
 {
 	SCORE_PRECOND(_VOID);
 
-	g_pManagerSound->SoundStateSet(idSound, state);
+	g_pManagerSound->soundSetState(idSound, state);
 }
 
-SX_LIB_API SOUND_OBJSTATE SSCore_SndStateGet(ID idSound)
+SX_LIB_API SOUND_OBJSTATE SSCore_SndGetState(ID idSound)
 {
 	SCORE_PRECOND(SOUND_OBJSTATE_STOP);
 
-	return g_pManagerSound->SoundStateGet(idSound);
+	return g_pManagerSound->soundGetState(idSound);
 }
 
-SX_LIB_API void SSCore_SndPosCurrSet(ID idSound, UINT uiPos, int iType)
+SX_LIB_API void SSCore_SndSetPosPlay(ID idSound, UINT uiPosMls)
 {
 	SCORE_PRECOND(_VOID);
 
-	g_pManagerSound->SoundPosCurrSet(idSound, uiPos, iType);
+	g_pManagerSound->soundSetPosPlay(idSound, uiPosMls);
 }
 
-SX_LIB_API UINT SSCore_SndPosCurrGet(ID idSound, int iType)
+SX_LIB_API UINT SSCore_SndGetPosPlay(ID idSound)
 {
 	SCORE_PRECOND(0);
 
-	return g_pManagerSound->SoundPosCurrGet(idSound, iType);
+	return g_pManagerSound->soundGetPosPlay(idSound);
 }
 
 
-SX_LIB_API void SSCore_SndVolumeSet(ID idSound, int iVolume, int iType)
+SX_LIB_API void SSCore_SndSetVolume(ID idSound, float fVolume)
 {
 	SCORE_PRECOND(_VOID);
 
-	g_pManagerSound->SoundVolumeSet(idSound, iVolume, iType);
+	g_pManagerSound->soundSetVolume(idSound, fVolume);
 }
 
-SX_LIB_API int SSCore_SndVolumeGet(ID idSound, int iType)
+SX_LIB_API float SSCore_SndGetVolume(ID idSound)
 {
 	SCORE_PRECOND(0);
 
-	return g_pManagerSound->SoundVolumeGet(idSound, iType);
+	return g_pManagerSound->soundGetVolume(idSound);
 }
 
 
-SX_LIB_API void SSCore_SndPanSet(ID idSound, int iValue, int iType)
+SX_LIB_API void SSCore_SndSetPan(ID idSound, float fValue)
 {
 	SCORE_PRECOND(_VOID);
 
-	g_pManagerSound->SoundPanSet(idSound, iValue, iType);
+	g_pManagerSound->soundSetPan(idSound, fValue);
 }
 
-SX_LIB_API int SSCore_SndPanGet(ID idSound, int iType)
+SX_LIB_API float SSCore_SndGetPan(ID idSound)
 {
 	SCORE_PRECOND(0);
 
-	return g_pManagerSound->SoundPanGet(idSound, iType);
+	return g_pManagerSound->soundGetPan(idSound);
 }
 
 
-SX_LIB_API void SSCore_SndFreqCurrSet(ID idSound, UINT fValue)
+SX_LIB_API void SSCore_SndSetCurrFreq(ID idSound, UINT fValue)
 {
 	SCORE_PRECOND(_VOID);
 
-	g_pManagerSound->SoundFreqCurrSet(idSound, fValue);
+	g_pManagerSound->soundSetFreqCurr(idSound, fValue);
 }
 
-SX_LIB_API UINT SSCore_SndFreqCurrGet(ID idSound)
+SX_LIB_API UINT SSCore_SndGetCurrFreq(ID idSound)
 {
 	SCORE_PRECOND(0);
 
-	return g_pManagerSound->SoundFreqCurrGet(idSound);
+	return g_pManagerSound->soundGetFreqCurr(idSound);
 }
 
-SX_LIB_API UINT SSCore_SndFreqOriginGet(ID idSound)
+SX_LIB_API UINT SSCore_SndGetOriginFreq(ID idSound)
 {
 	SCORE_PRECOND(0);
 
-	return g_pManagerSound->SoundFreqOriginGet(idSound);
+	return g_pManagerSound->soundGetFreqOrigin(idSound);
 }
 
-SX_LIB_API void SSCore_SndPosWSet(ID idSound, const float3 *pPos)
+SX_LIB_API void SSCore_SndSetPosWorld(ID idSound, const float3 *pPos)
 {
 	SCORE_PRECOND(_VOID);
 
-	g_pManagerSound->SoundPosWSet(idSound, pPos);
+	g_pManagerSound->soundSetPosWorld(idSound, pPos);
 }
 
-SX_LIB_API void SSCore_SndPosWGet(ID idSound, float3 *pPos)
+SX_LIB_API void SSCore_SndGetPosWorld(ID idSound, float3 *pPos)
 {
 	SCORE_PRECOND(_VOID);
 
-	g_pManagerSound->SoundPosWGet(idSound, pPos);
+	g_pManagerSound->soundGetPosWorld(idSound, pPos);
 }
 
 
-SX_LIB_API int SSCore_SndLengthSecGet(ID idSound)
+SX_LIB_API int SSCore_SndGetLengthSec(ID idSound)
 {
 	SCORE_PRECOND(0);
 
-	return g_pManagerSound->SoundLengthSecGet(idSound);
+	return g_pManagerSound->soundGetLengthSec(idSound);
 }
 
-SX_LIB_API UINT SSCore_SndBytesPerSecGet(ID idSound)
+SX_LIB_API UINT SSCore_SndGetBytesPerSec(ID idSound)
 {
 	SCORE_PRECOND(0);
 
-	return g_pManagerSound->SoundBytesPerSecGet(idSound);
+	return g_pManagerSound->soundGetBytesPerSec(idSound);
 }
 
-SX_LIB_API UINT SSCore_SndSizeGet(ID idSound)
+SX_LIB_API UINT SSCore_SndGetSize(ID idSound)
 {
 	SCORE_PRECOND(0);
 
-	return g_pManagerSound->SoundSizeGet(idSound);
+	return g_pManagerSound->soundGetSize(idSound);
 }
 
-SX_LIB_API void SSCore_SndFileGet(ID idSound, char *szPath)
+SX_LIB_API void SSCore_SndGetFile(ID idSound, char *szPath)
 {
 	SCORE_PRECOND(_VOID);
 
-	g_pManagerSound->SoundFileGet(idSound, szPath);
+	g_pManagerSound->soundGetFile(idSound, szPath);
 }
 
 
-SX_LIB_API float SSCore_SndDistAudibleGet(ID idSound)
+SX_LIB_API float SSCore_SndGetDistAudible(ID idSound)
 {
 	SCORE_PRECOND(0);
 
-	return g_pManagerSound->SoundDistAudibleGet(idSound);
+	return g_pManagerSound->soundGetDistAudible(idSound);
+}
+
+SX_LIB_API void SSCore_SndSetDistAudible(ID idSound, float fValue)
+{
+	SCORE_PRECOND(_VOID);
+
+	g_pManagerSound->soundSetDistAudible(idSound, fValue);
+}
+
+//##########################################################################
+
+SX_LIB_API ID SSCore_SndkitCreate(const char *szName, ID idChannel, bool is3D, float fDistAudible)
+{
+	SCORE_PRECOND(-1);
+
+	return g_pManagerSound->sndkitCreate(szName, idChannel, is3D, fDistAudible);
+}
+
+SX_LIB_API ID SSCore_SndkitCreateFromList(const char *szName, ID idChannel, bool is3D, float fDistAudible, float fVolume, const char *szFileOrList, ...)
+{
+	SCORE_PRECOND(-1);
+
+	Array<String> aStrings;
+	// если в первой строке есть запятые тогда будем парсить строку
+	if (strstr(szFileOrList, ","))
+	{
+		aStrings = StrExplode(szFileOrList, ",");
+	}
+	// иначе считываем все строчные аргументы
+	else if (szFileOrList)
+	{
+		const char *szStrCurr = 0;
+		va_list va;
+		va_start(va, szFileOrList);
+
+		szStrCurr = szFileOrList;
+		while (szStrCurr)
+		{
+			aStrings.push_back(szStrCurr);
+			szStrCurr = va_arg(va, const char *);
+		}
+
+		va_end(va);
+	}
+
+	return g_pManagerSound->sndkitCreateFromList(szName, idChannel, aStrings, is3D, fDistAudible, fVolume);
 }
 
-SX_LIB_API void SSCore_SndDistAudibleSet(ID idSound, float fValue)
+SX_LIB_API void SSCore_SndkitAddSound(ID idSndKit, const char *szFile, float fDistAudible, float fVolume, UINT *pArrDelay, int iSizeArrDelay)
 {
 	SCORE_PRECOND(_VOID);
 
-	g_pManagerSound->SoundDistAudibleSet(idSound, fValue);
+	g_pManagerSound->sndkitAddSound(idSndKit, szFile, fDistAudible, fVolume, pArrDelay, iSizeArrDelay);
 }
+
+SX_LIB_API uint64_t SSCore_SndkitPlay(ID idSndKit, uint64_t id2, const float3 *pPos, float fVolume, float fPan)
+{
+	SCORE_PRECOND(-1);
+
+	return g_pManagerSound->sndkitPlay(idSndKit, id2, pPos, fVolume, fPan);
+}
+
+SX_LIB_API void SSCore_SndkitStop(ID idSndKit, uint64_t id2)
+{
+	SCORE_PRECOND(_VOID);
+
+	g_pManagerSound->sndkitStop(idSndKit, id2);
+}
+
+SX_LIB_API ID SSCore_SndkitGetID(const char *szName)
+{
+	SCORE_PRECOND(-1);
+
+	return g_pManagerSound->sndkitGetID(szName);
+}
+
+SX_LIB_API ID SSCore_SndkitGetChannel(ID idSndKit)
+{
+	SCORE_PRECOND(-1);
+
+	return g_pManagerSound->sndkitGetChannel(idSndKit);
+}
+
+SX_LIB_API void SSCore_SndkitGetName(ID idSndKit, char *szName)
+{
+	SCORE_PRECOND(_VOID);
+
+	g_pManagerSound->sndkitGetName(idSndKit, szName);
+}
+
+SX_LIB_API void SSCore_SndkitDelete(ID idSndKit)
+{
+	SCORE_PRECOND(_VOID);
+
+	g_pManagerSound->sndkitDelete(idSndKit);
+}
+
+SX_LIB_API void SSCore_SndkitDeleteAll()
+{
+	SCORE_PRECOND(_VOID);
+
+	g_pManagerSound->sndkitDeleteAll();
+}
\ No newline at end of file
diff --git a/source/score/sxscore.h b/source/score/sxscore.h
index 05472b192f826f93ca89438953b55c8265245ca9..720b23952a27f0aa5e20fd74a9f9cf6f82f87513 100644
--- a/source/score/sxscore.h
+++ b/source/score/sxscore.h
@@ -16,9 +16,15 @@ See the license in LICENSE
  - "Ogg Vorbis" (загрузка ogg файлов).
  \note Загружаемые звуки wav и ogg формата (автоматическое определение и загрузка нужных данных).
  \note Поддерживаются 2d и 3d звуки, полная загрузка и потоковое воспроизвдение.
- \note Также для полностью загруженных (не потоковое воспроизведение) доступно воспроизвдение инстансов (копий), без выдеения дополнительной равноценной памяти, и без дополнительных возможностей управления инстансом.
+ \note Также для полностью загруженных (не потоковое воспроизведение) доступно воспроизвдение инстансов (копий), без выделения дополнительной равноценной памяти, и без дополнительных возможностей управления инстансом.
 Однако источник выдачи инстансов должен быть создан одной из функций #SSCore_SndInstancePlay2d #SSCore_SndInstancePlay3d
  \note Идентификация звука происходит на основании его числового идентификатора выдаваемого создаваемыми функциями (#SSCore_SndCreate2d/#SSCore_SndCreate2dInst #SSCore_SndCreate3d/#SSCore_SndCreate3dInst) и является константной, идентификатор является порядковым номером
+ \note каждый звук, который проигрывается не потоково, может проигрываться с задержками
+ \note каждый звук может загружаться с настройками прямо в строке, при этом настройки в строке будут приоритетными, формат строки следующий:
+путь_до_файла_без_пробелов  dдистанция_слышимости_в_метрах vгромкость_от_0_до_1 задержка_перед_проигрыванием_в_млсек задержка2_в_млсек ... \n
+данные громкости и дальности должны быть первыми (но между собой у них нет правила), и только после них идут задержки \n
+на пример: messages/artefact_lead.ogg d100 v1.0 300 300 300 \n
+парсинг строки осуществляется на основании пробелов, то есть в имени файла недопустимы пробелы
 @{*/
 
 #ifndef __SXSCORE_H
@@ -67,15 +73,52 @@ SX_LIB_API void SSCore_AKill();
 
 //#############################################################################
 
-/*! абсолюный путь до директории с файлами */
+/*! размер абсолюного пути до директории с файлами */
 #define SOUND_MAX_SIZE_STDPATH	256	
 
-/*! относительный путь до файла со звуком */
+/*! размер относительного пути до файла со звуком */
 #define SOUND_MAX_SIZE_PATH		128	
 
+/*! размер полного пути до файла со звуком */
+#define SOUND_MAX_SIZE_FULLPATH	(SOUND_MAX_SIZE_STDPATH + SOUND_MAX_SIZE_PATH)
+
 /*! минимально возможный размер потока для воспроизведения */
 #define SOUND_MIN_SIZE_STREAM	1024*64 
 
+/*! ошибочный идентификатор */
+#define SOUND_FAIL_ID	-1
+
+
+/*! коэффициент смещения между ушами слушателя для 3d звуков */
+#define SOUND_SHIFTPAN_3D	0.1f
+
+/*! дистанция слышимости по умолчанию, в метрах */
+#define SOUND_DIST_AUDIBLE_DEFAULT	100
+
+
+/*! максимальное количество каналов */
+#define SOUND_CHANNELS_COUNT	100
+
+
+/*! упаковка двух int32_t в uint64_t */
+#define SOUND_ENCODE2ID(id1, id2)( (((uint64_t)((uint32_t)id1))<<32) | (uint32_t)id2 )
+
+/*! извлечение первого int32_t из uint64_t из старших битов */
+#define SOUND_DECODE2ID_HI(id)( (int32_t)(uint32_t)(((uint64_t)id) >> 32) )
+
+/*! извлечение первого int32_t из uint64_t из младших битов */
+#define SOUND_DECODE2ID_LO(id)( (int32_t)(uint32_t)(((uint64_t)id) & 0xFFFFFFFF) )
+
+
+/*! масимальная длина имени набора звуков */
+#define SOUND_MAX_SIZE_SNDKIT_NAME	128	
+
+/*! блокировать инстанс набора */
+#define SOUND_SNDKIT_INSTANCE_BLOCK		-1
+
+/*! не блокировать инстанс набора */
+#define SOUND_SNDKIT_INSTANCE_NOTBLOCK	-2
+
 //**************************************************************************
 
 /*! \name Данные для первичного буфера
@@ -92,25 +135,12 @@ SX_LIB_API void SSCore_AKill();
 
 //!@}
 
-//**************************************************************************
-
 /*! количество бит на сэмпл для ogg, возможно 8 или 16 */
 #define SOUND_OGG_BITS_PER_SAMPLE	16	
 
 /*! тип количества бит на сэмпл для ogg, 1 - для 8 бит, 2 - для 16 */
 #define SOUND_OGG_BITS_PER_SAMPLE_WORD SOUND_OGG_BITS_PER_SAMPLE/8
 
-#define SOUND_POS_BYTES	0	/*!< байты */
-#define SOUND_POS_SEC	1	/*!< секунды */
-#define SOUND_POS_MLS	2	/*!< млсек */
-
-#define SOUND_VOL_DB	0	/*!< децибелы */
-#define SOUND_VOL_PCT	1	/*!< проценты */
-
-#define SOUND_EFF_ON	1	/*!< включение эффекта */
-#define SOUND_EFF_OFF	0	/*!< выключение эффекта */
-#define SOUND_EFF_INVALID_KEY	-1	/*!< неверно указан ключ при обращении к функциям эффектов */
-
 //#############################################################################
 
 //! форматы звукрвых файлов
@@ -129,6 +159,22 @@ enum SOUND_OBJSTATE
 	SOUND_OBJSTATE_PLAY,	//!< проигрывается
 };
 
+//! остояние занятости инстансов
+enum SOUND_SNDINSTANCE_BUSY
+{
+	SOUND_SNDINSTANCE_BUSY_FREE,	/*!< свободный */
+	SOUND_SNDINSTANCE_BUSY_TEMP,	/*!< времено занятый */
+	SOUND_SNDINSTANCE_BUSY_LOCKED,	/*!< заблокированный владельцем */
+};
+
+//! значения каналов
+enum SOUND_CHANNEL
+{
+	SOUND_CHANNEL_NONE = -1,	/*!< значение не инициализованного канала */
+	SOUND_CHANNEL_STOP = 0,		/*!< значение не проигрывающегося в данный момент канала */
+	SOUND_CHANNEL_PLAY = 1,		/*!< значение проигрывающегося в данный момент канала */
+};
+
 //#############################################################################
 
 //! очистка всего списка звуков (полное их удаление)
@@ -141,52 +187,110 @@ SX_LIB_API void SSCore_Update(
 	);	
 
 //! количество проигрываемых на данный момент звуков
-SX_LIB_API int SSCore_SndsPlayCountGet();	
+SX_LIB_API int SSCore_SndsGetCountPlay();
 
 //! количество загруженных на данный момент звуков
-SX_LIB_API int SSCore_SndsLoadCountGet();	
+SX_LIB_API int SSCore_SndsGetCountLoad();
+
+//##########################################################################
+
+//! добавить канал
+SX_LIB_API void SSCore_ChannelAdd(ID idChannel, bool isPlaying = false);
+
+//! существует ли канал
+SX_LIB_API bool SSCore_ChannelExists(ID idChannel);
+
+//! количество звуков в канале
+SX_LIB_API int SSCore_ChannelGetSndCount(ID idChannel);
+
+//! проигрывать звуки канала
+SX_LIB_API void SSCore_ChannelPlay(ID idChannel);
+
+//! проигрывать звуки только этого канала
+SX_LIB_API void SSCore_ChannelPlayOnly(ID idChannel);
+
+//! проигрывается ли канал?
+SX_LIB_API bool SSCore_ChannelPlaying(ID idChannel);
+
+//! остановить проигрывание звуков канала
+SX_LIB_API void SSCore_ChannelStop(ID idChannel);
+
+//###############################################################################
 
 //! загрузка 2d (фонового) звука
 SX_LIB_API ID SSCore_SndCreate2d(
 	const char *szFile,		//!< путь до файла, относительно стандартного
-	bool isLooping = false,	//!< зацикливать ли воспроизведение
+	ID idChannel,			//!< идентификатор канала
 	UINT uiSizeStream = 0	//!< размер потока в байтах для потокового воспроизведения, если 0 тогда полностью грузить в память
 	);
 
 //! загрузка 3d звука
 SX_LIB_API ID SSCore_SndCreate3d(
 	const char *szFile,		//!< путь до файла, относительно стандартного
-	bool isLooping,			//!< зацикливать ли воспроизведение
+	ID idChannel,			//!< идентификатор канала
 	UINT uiSizeStream,		//!< размер потока в байтах для потокового воспроизведения, если 0 тогда полностью грузить в память
-	float fDist,			//!< радиус слышимости в метрах
-	float fShiftPan = 0.1f	//!< изменение позиционирования звука [0-1], на сколько будет смещен звук (между ушами слушателя) при поворотах камеры к источнику звука, чем ближе к объекту тем меньше разница в позиционировании при поворотах
+	float fDist				//!< радиус слышимости в метрах
 	);
 
-//! воспроизведение инстанса 2d звука
-SX_LIB_API void SSCore_SndInstancePlay2d(
-	ID idSound,			//!< идентификатор звука
-	int iVolume = 100,	//!< громкость [0-100]
-	int iPan = 0		//!< смещение между ушами [-100 - 100]
-	);
-
-//! воспроизведение инстанса 3d звука
-SX_LIB_API void SSCore_SndInstancePlay3d(
-	ID idSound,			//!< идентификатор звука
-	const float3 *pPos	//!< позиция воспроизведения инстанса
-	);
+//###############################################################################
 
 //! загрузка 2d звукового файла и пометка его как объект выдающий инстансы, аргументы аналогичны #SSCore_SndCreate2d
-SX_LIB_API ID SSCore_SndCreate2dInst(const char *szFile, bool isLooping = false, UINT uiSizeStream = 0);
+SX_LIB_API ID SSCore_SndCreate2dInst(const char *szFile, ID idChannel);
 
 //! загрузка 3d звукового файла и пометка его как объект выдающий инстансы, аргументы аналогичны #SSCore_SndCreate3d
-SX_LIB_API ID SSCore_SndCreate3dInst(const char *szFile, bool isLooping, UINT uiSizeStream, float fDist, float fShiftPan = 0.1f);
+SX_LIB_API ID SSCore_SndCreate3dInst(const char *szFile, ID idChannel, float fDist);
+
+//**************************************************************************
 
 //! поиск 2d звука (выдающего инстансы) по относительному пути загрузки,возвращает его ID (в случае успеха) иначе <0
-SX_LIB_API ID SSCore_SndFind2dInst(const char *szFile);
+SX_LIB_API ID SSCore_SndFind2dInst(const char *szFile, ID idChannel);
 
 //! поиск 3d звука (выдающего инстансы) по относительному пути загрузки,возвращает его ID (в случае успеха) иначе <0
-SX_LIB_API ID SSCore_SndFind3dInst(const char *szFile);
+SX_LIB_API ID SSCore_SndFind3dInst(const char *szFile, ID idChannel);
+
+//**************************************************************************
+
+/*! воспроизведение инстанса звука, если нужны задержки то надо их указывать в pArrDelay и iSizeArrDelay, иначе в обоих 0, если указать iSizeArrDelay = -1 тогда будут задействованы предыдущие настройки
+если нужен 3д звук (если это на самом деле 3д звук) то надо указать pPos, иначе 0 и будет 2д, для 2д по желанию можно указать громкость iVolume и смещение между ушами iPan
+*/
+SX_LIB_API ID SSCore_SndInstancePlay(
+	ID idSound,				//!< идентификатор звука
+	bool isBlocked,			//!< блокировать ли файл? если true то вернет id который будет занят до тех пор пока его не освободит владалец через #SSCore_SndInstanceFree
+	bool isLooping,			//!< зацикливать ли воспроизведение звука? если да то звук будет заблокирован, а возвращенный id будет приндалежать вызывавшему и именно он несет ответсвенность за остановку и освобождение инстанса
+	UINT *pArrDelay,		//!< массив задержек в млсек, первое значение задержка перед воспроизведением
+	int iSizeArrDelay,		//!< размер #pArrDelay
+	const float3 *pPos,		//!< если это 3д звук то позиция обязательна, если 2д то нужно указать NULL
+	float fVolume = 1.f,	//!< громкость [0, 1]
+	float fPan = 0.f		//!< смещение между ушами [-1, 1]
+	);
+
+//! воспроизведение инстанса 2d звука, аргументы аналогичны #SSCore_SndInstancePlay
+#define SSCore_SndInstancePlay2d(idSound, isBlocked, isLooping, iVolume, iPan) (SSCore_SndInstancePlay(idSound, isBlocked, isLooping, 0, 0, 0, iVolume, iPan))
+
+//! воспроизведение инстанса 2d звука с задержками, аргументы аналогичны #SSCore_SndInstancePlay
+#define SSCore_SndInstancePlayDelay2d(idSound, isBlocked, isLooping, pArrDelay, iSizeArrDelay, iVolume, iPan) (SSCore_SndInstancePlay(idSound, isBlocked, isLooping, pArrDelay, iSizeArrDelay, 0, iVolume, iPan))
 
+//! воспроизведение инстанса 3d звука, аргументы аналогичны #SSCore_SndInstancePlay
+#define SSCore_SndInstancePlay3d(idSound, isBlocked, isLooping, pPos) (SSCore_SndInstancePlay(idSound, isBlocked, isLooping, 0, 0, pPos))
+
+//! воспроизведение инстанса 3d звука с задержками, аргументы аналогичны #SSCore_SndInstancePlay
+#define SSCore_SndInstancePlayDelay3d(idSound, isBlocked, isLooping, pArrDelay, iSizeArrDelay, pPos) (SSCore_SndInstancePlay(idSound, isBlocked, isLooping, pArrDelay, iSizeArrDelay, pPos))
+
+//**************************************************************************
+
+//! проигрывается ли инстанс звука с id idInstance
+SX_LIB_API bool SSCore_SndInstancePlaying(
+	ID idSound,		//!< идентификатор звука
+	ID idInstance	//!< идентификатор инстанса звука который был возвращен функцией #SSCore_SndInstancePlay2d или #SSCore_SndInstancePlay3d
+	);
+
+//! остановка инстанса звука с id idInstance
+SX_LIB_API void SSCore_SndInstanceStop(ID idSound, ID idInstance);
+
+//! освобождает инстанс звука с id idInstance, будет иметь статус занятости #SOUND_SNDINSTANCE_BUSY_TEMP если был #SOUND_SNDINSTANCE_BUSY_LOCKED, а при следующем обновлении если инстанс не проигрывается статус поменяется на #SOUND_SNDINSTANCE_BUSY_FREE
+SX_LIB_API void SSCore_SndInstanceFree(ID idSound, ID idInstance);
+
+//###############################################################################
 
 //! инициализирован ли звук с идентификатором id
 SX_LIB_API bool SSCore_SndIsInit(ID idSound);
@@ -194,9 +298,15 @@ SX_LIB_API bool SSCore_SndIsInit(ID idSound);
 //! удалить звук по его id
 SX_LIB_API void SSCore_SndDelete(ID idSound);
 
+//###############################################################################
 
-//! воспроизвести звук, looping зацикливать ли воспроизведение, 0 - нет, >0 да, <0 не учитывать данное значение
-SX_LIB_API void	SSCore_SndPlay(ID idSound, int looping = -1);
+//! воспроизвести звук, isLooping зацикливать ли воспроизведение
+SX_LIB_API void	SSCore_SndPlay(
+	ID idSound,				//!< идентификатор звука
+	bool isLooping = false,	//!< зацикливать ли воспроизведение?
+	UINT *pArrDelay = 0,	//!< массив задержек в млсек, первое значение задержка перед воспроизведением
+	int iSizeArrDelay = 0	//!< размер массива pArrDelay, если указать iSizeArrDelay = -1 тогда будут задействованы предыдущие настройки
+	);
 
 //! приостановить
 SX_LIB_API void	SSCore_SndPause(ID idSound);
@@ -206,89 +316,177 @@ SX_LIB_API void	SSCore_SndStop(ID idSound);
 
 
 //! устанавливает состояние проигрывания звука
-SX_LIB_API void SSCore_SndStateSet(ID idSound, SOUND_OBJSTATE state);
+SX_LIB_API void SSCore_SndSetState(ID idSound, SOUND_OBJSTATE state);
 
 //! возвращает состояние проигрывания звука на данный момент
-SX_LIB_API SOUND_OBJSTATE SSCore_SndStateGet(ID idSound);
+SX_LIB_API SOUND_OBJSTATE SSCore_SndGetState(ID idSound);
+
+//**************************************************************************
 
 //! устанавить позицию проигрывания
-SX_LIB_API void SSCore_SndPosCurrSet(
-	ID idSound,					//!< идентификатор звука
-	UINT uiPos,					//!< значение позиции исходя из параметра type
-	int iType = SOUND_POS_BYTES	//!< тип значения pos, SOUND_POS_
+SX_LIB_API void SSCore_SndSetPosPlay(
+	ID idSound,		//!< идентификатор звука
+	UINT uiPosMls	//!< значение позиции в млсек
 	);	
 
 //! возвращает позицию проигрывания
-SX_LIB_API UINT SSCore_SndPosCurrGet(
-	ID idSound,					//!< идентификатор звука
-	int iType = SOUND_POS_BYTES	//!< тип возвращаемого значения, SOUND_POS_
-	);
+SX_LIB_API UINT SSCore_SndGetPosPlay(ID idSound);
 
 //! устанавить громкость
-SX_LIB_API void SSCore_SndVolumeSet(
-	ID idSound,					//!< идентификатор звука
-	int iVolume,				//!< значение громкости исходя из параметра type
-	int iType = SOUND_VOL_PCT	//!< тип значения volume, SOUND_VOL_
+SX_LIB_API void SSCore_SndSetVolume(
+	ID idSound,		//!< идентификатор звука
+	float fVolume	//!< значение громкости [0, 1]
 	);
 
-//! возвращает громкость
-SX_LIB_API int SSCore_SndVolumeGet(
-	ID idSound,					//!< идентификатор звука
-	int iType = SOUND_VOL_PCT	//!< тип возвращаемого значения, SOUND_VOL_
-	);
+//! возвращает громкость [0, 1]
+SX_LIB_API float SSCore_SndGetVolume(ID idSound);
 
 //! установка позиционирования между ушами
-SX_LIB_API void SSCore_SndPanSet(
-	ID idSound,					//!< идентификатор звука
-	int iValue,					//!< значение позиционирования исходя из параметра type
-	int iType = SOUND_VOL_PCT	//!< тип значения value, SOUND_VOL_
+SX_LIB_API void SSCore_SndSetPan(
+	ID idSound,		//!< идентификатор звука
+	float fValue	//!< значение позиционирования [-1, 1]
 	);
 
-//! возвращает позиционирование между ушами
-SX_LIB_API int SSCore_SndPanGet(
-	ID idSound,						//!< идентификатор звука
-	int type = SOUND_VOL_PCT	//!< тип возвращаемого значения, SOUND_VOL_
-	);
+//! возвращает позиционирование между ушами [-1, 1]
+SX_LIB_API float SSCore_SndGetPan(ID idSound);
 
 
 //! установка частоты воспроизведения
-SX_LIB_API void SSCore_SndFreqCurrSet(ID idSound, UINT uiValue);
+SX_LIB_API void SSCore_SndSetCurrFreq(ID idSound, UINT uiValue);
 
 //! возвращает текущую частоту воспроизведения
-SX_LIB_API UINT SSCore_SndFreqCurrGet(ID idSound);
+SX_LIB_API UINT SSCore_SndGetCurrFreq(ID idSound);
 
 //! возвращает оригинальную частоту воспроизведения
-SX_LIB_API UINT SSCore_SndFreqOriginGet(ID idSound);
+SX_LIB_API UINT SSCore_SndGetOriginFreq(ID idSound);
 
 
 //! установка мировой позиции звука (только для 3d звуков)
-SX_LIB_API void SSCore_SndPosWSet(ID idSound, const float3 *pPos);
+SX_LIB_API void SSCore_SndSetPosWorld(ID idSound, const float3 *pPos);
 
 //! возвращает мировую позицию звука (только для 3d звуков)
-SX_LIB_API void SSCore_SndPosWGet(ID idSound, float3 *pPos);
+SX_LIB_API void SSCore_SndGetPosWorld(ID idSound, float3 *pPos);
 
 
 //! длина в секундах
-SX_LIB_API int SSCore_SndLengthSecGet(ID idSound);
+SX_LIB_API int SSCore_SndGetLengthSec(ID idSound);
 
 //! количество байт в секунде
-SX_LIB_API UINT SSCore_SndBytesPerSecGet(ID idSound);
+SX_LIB_API UINT SSCore_SndGetBytesPerSec(ID idSound);
 
 //! размер в байтах PCM данных
-SX_LIB_API UINT SSCore_SndSizeGet(ID idSound);
+SX_LIB_API UINT SSCore_SndGetSize(ID idSound);
 
 //! относительный путь до звукового файла
-SX_LIB_API void SSCore_SndFileGet(ID idSound, char *szPath);		
+SX_LIB_API void SSCore_SndGetFile(ID idSound, char *szPath);
 
 
 //! возвращает дистанцию слышимости
-SX_LIB_API float SSCore_SndDistAudibleGet(ID idSound);
+SX_LIB_API float SSCore_SndGetDistAudible(ID idSound);
 
 //! установка дистанции слышимости в метрах
-SX_LIB_API void SSCore_SndDistAudibleSet(ID idSound, float fVfalue);
+SX_LIB_API void SSCore_SndSetDistAudible(ID idSound, float fVfalue);
+
+//!@}
+
+//###############################################################################
+
+/*! \name Наборы звуков для воспроизведения случайного звука из набора
+ \note Все звуки создаются инстансовыми
+@{*/
+
+//! создать набор звуков
+SX_LIB_API ID SSCore_SndkitCreate(
+	const char *szName,			//!< имя набора
+	ID idChannel,				//!< id канала
+	bool is3D,					//!< набор 3д звуков?
+	float fDistAudible = SOUND_DIST_AUDIBLE_DEFAULT	//!< дистанция слышимости
+	);
+
+//! загрузить список звуков (с настройками) из строки либо из строк
+SX_LIB_API ID SSCore_SndkitCreateFromList(
+	const char *szName,			//!< имя набора
+	ID idChannel,				//!< id канала
+	bool is3D,					//!< набор 3д звуков?
+	float fDistAudible,			//!< дистанция слышимости
+	float fVolume,				//!< громкость [0, 1]
+	const char *szFileOrList,	//!< строка с первым файлом и настройками (последующие аргументы учитываются), либо строка со всеми файлами (через запятую) и настройками (последующие аргументы не учитываются)
+	...							//!< если #szFileOrList один файл тогда здесь должны быть строки с файлами до звуков (с настройками)
+	);
+
+//**************************************************************************
+
+//! добавить звук в набор
+SX_LIB_API void SSCore_SndkitAddSound(
+	ID idSndKit,			//!< id набора
+	const char *szFile,		//!< путь к файлу звука
+	float fDistAudible,		//!< дистанция слышимости для 3d звуков, для 2d можно просто 0, если < 0 тогда установит то значение которое было передано в #SSCore_SndkitCreate
+	float fVolume = 1.f,	//!< громскость [0, 1]
+	UINT *pArrDelay = 0,	//!< массив задержек
+	int iSizeArrDelay = 0	//!< количество элементов в #pArrDelay
+	);
+
+//! добавить в набор 2d звук
+#define SSCore_SndkitAddSound2d(idSndKit, szFile, fVolume) (SSCore_SndkitAddSound(idSndKit, szFile, 0, fVolume, 0, 0))
+
+//! добавить в набор 2d звук с задержками при воспроизведении
+#define SSCore_SndkitAddSoundDelay2d(idSndKit, szFile, fVolume, pArrDelay, iSizeArrDelay) (SSCore_SndkitAddSound(idSndKit, szFile, 0, fVolume, pArrDelay, iSizeArrDelay))
+
+//! добавить в набор 3d звук
+#define SSCore_SndkitAddSound3d(idSndKit, szFile, fDistAudible, fVolume) (SSCore_SndkitAddSound(idSndKit, szFile, fDistAudible, fVolume, 0, 0))
+
+//! добавить в набор 3d звук с задержками при воспроизведении
+#define SSCore_SndkitAddSoundDelay3d(idSndKit, szFile, fDistAudible, fVolume, pArrDelay, iSizeArrDelay) (SSCore_SndkitAddSound(idSndKit, szFile, fDistAudible, fVolume, pArrDelay, iSizeArrDelay))
+
+//**************************************************************************
+
+/*! проиграть случайны звук
+ \note если набор 3д звуков, то позиция обязательна
+ \note id2 должен принимать либо #SOUND_SNDKIT_INSTANCE_BLOCK либо #SOUND_SNDKIT_INSTANCE_NOTBLOCK либо должен быть упакованным значением идентификаторов заблокированного инстанса звука
+если инстанс воспроизводимого звука заблокирован, то он не будет использоваться другими пока владелец его не разблокирует
+если было передано упакованное значение, и инстанс уже отыграл свое, значит он разблокируется и будет воспроизведен другой инстанс и заблокируется
+ \return возвращает упакованные значения порядкового номера звука (в массиве набора) в 32 старших битах и id инстанса звука в 32 младших битах
+*/
+SX_LIB_API uint64_t SSCore_SndkitPlay(
+	ID idSndKit,			//!< id набора 
+	uint64_t id2,			//!< либо #SOUND_SNDKIT_INSTANCE_BLOCK либо #SOUND_SNDKIT_INSTANCE_NOTBLOCK либо должен быть упакованным значением идентификаторов заблокированного инстанса звука
+	const float3 *pPos = 0, //!< если 3d, позиция звука в пространстве
+	float fVolume = -1.f,	//!< громкость [0, 1], если <0 тогда будет использовано ранее заданное значение
+	float fPan = 0.f		//!< если 2d, смещение между ушами [-1, 1]
+	);
+
+//! проиграть случайны звук из 2d набора, аргументы аналогичны #SSCore_SndkitPlay
+#define SSCore_SndkitPlay2d(idSndKit, id2, fVolume, fPan) (SSCore_SndkitPlay(idSndKit, id2, 0, fVolume, fPan))
+
+//! проиграть случайны звук из 3d набора, аргументы аналогичны #SSCore_SndkitPlay
+#define SSCore_SndkitPlay3d(idSndKit, id2, pPos) (SSCore_SndkitPlay(idSndKit, id2, pPos))
+
+//! остановить проигрывание звуков в наборе 
+SX_LIB_API void SSCore_SndkitStop(
+	ID idSndKit,	//!< id набора 
+	uint64_t id2	//!< результат SSCore_SndkitPlay если параметр id2 имел значение отличное от #SOUND_SNDKIT_INSTANCE_NOTBLOCK
+	);
+
+//**************************************************************************
+
+//! получить id по имени набора
+SX_LIB_API ID SSCore_SndkitGetID(const char *szName);
+
+//! получить номер канала
+SX_LIB_API ID SSCore_SndkitGetChannel(ID idSndKit);
+
+//! получить имя по id набора
+SX_LIB_API void SSCore_SndkitGetName(ID idSndKit, char *szName);
+
+//! удалить набор
+SX_LIB_API void SSCore_SndkitDelete(ID idSndKit);
+
+//! удалить все наборы
+SX_LIB_API void SSCore_SndkitDeleteAll();
 
 //!@}
 
+
 #endif
 
 //!@} sxscore
diff --git a/source/skyxengine.cpp b/source/skyxengine.cpp
index b2e1b62e1d1a92d3e7a12049744b221aa6b6f3c4..3390f448595f28b49363e3173e993ac3d52b979e 100644
--- a/source/skyxengine.cpp
+++ b/source/skyxengine.cpp
@@ -193,6 +193,8 @@ void SkyXEngine_Init(HWND hWnd3D, HWND hWndParent3D)
 
 	SSCore_0Create("sxsound", hWnd3DCurr, false);
 	SSCore_Dbg_Set(SkyXEngine_PrintfLog);
+	SSCore_ChannelAdd(SX_SOUND_CHANNEL_GAME, true);
+	//SSCore_SndkitCreateFromList("test", SX_SOUND_CHANNEL_GAME, false, 0, 1.f, " messages/artefact_lead.ogg  d100   v1.0  300   300    300 , messages/artefact_lose.ogg d50 v0.7 400 400 400, messages/artefact_lost.ogg d30 v1.0 200 200 200, messages/artefact_new.ogg d35 v0.9 250 250 250");
 
 	SGCore_0Create("sxgcore", hWnd3DCurr, *r_win_width, *r_win_height, *r_win_windowed, 0, false);
 	SGCore_Dbg_Set(SkyXEngine_PrintfLog);
@@ -668,7 +670,8 @@ void SkyXEngine_Frame(DWORD timeDelta)
 
 #if defined(SX_GAME)
 	ttime = TimeGetMcsU(Core_RIntGet(G_RI_INT_TIMER_RENDER));
-	SRender_RenderPostProcess(timeDelta);
+	if (!SSInput_GetKeyState(SIK_P))
+		SRender_RenderPostProcess(timeDelta);
 	DelayPostProcess += TimeGetMcsU(Core_RIntGet(G_RI_INT_TIMER_RENDER)) - ttime;
 #endif
 
@@ -803,11 +806,11 @@ void SkyXEngine_Frame(DWORD timeDelta)
 	SPE_EffectComputeAll();
 	SPE_EffectComputeLightingAll();
 	DelayUpdateParticles += TimeGetMcsU(Core_RIntGet(G_RI_INT_TIMER_RENDER)) - ttime;
-
+	
 	ttime = TimeGetMcsU(Core_RIntGet(G_RI_INT_TIMER_RENDER));
 	pDXDevice->Present(0, 0, 0, 0);
 	DelayPresent += TimeGetMcsU(Core_RIntGet(G_RI_INT_TIMER_RENDER)) - ttime;
-
+	
 	SkyXEngind_UpdateDataCVar();
 }
 
@@ -1024,6 +1027,7 @@ void SkyXEngind_UpdateDataCVar()
 
 int SkyXEngine_CycleMain()
 {
+	//ID idSnd = SSCore_SndCreate2dInst("ak74_reload.ogg",SX_SOUND_CHANNEL_GAME);
 	MSG msg;
 	::ZeroMemory(&msg, sizeof(MSG));
 
@@ -1046,8 +1050,28 @@ int SkyXEngine_CycleMain()
 		}
 		else
 		{
-			SGCore_LoadTexAllLoad();
 			SGCore_ShaderAllLoad();
+			SGCore_LoadTexAllLoad();
+
+			/*if (SSInput_GetKeyState(SIK_BACKSPACE))
+				SSCore_ChannelPlay(SX_SOUND_CHANNEL_GAME);
+			else if (SSInput_GetKeyState(SIK_ENTER))
+				SSCore_ChannelStop(SX_SOUND_CHANNEL_GAME);
+
+			UINT arr[] = {3000, 350, 1000, 800, 300 };
+			if (SSInput_GetKeyState(SIK_RSHIFT))
+				SSCore_SndInstancePlayDelay2d(idSnd, false, true, arr, 5, 1, 0);
+
+			if (SSInput_GetKeyState(SIK_RCONTROL))
+				SSCore_SndStop(idSnd);
+
+			//
+			static uint64_t id2 = SOUND_SNDKIT_INSTANCE_BLOCK;
+			id2 = SSCore_SndkitPlay(0, id2);
+			if (SSInput_GetKeyState(SIK_TAB))
+				SSCore_SndkitStop(0, id2);*/
+
+			
 			Core_TimesUpdate();
 			Core_0ConsoleUpdate();
 			SSInput_Update();