<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://stalkerin.gameru.net/wiki/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://stalkerin.gameru.net/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=94.141.39.153&amp;*</id>
		<title>S.T.A.L.K.E.R. Inside Wiki - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://stalkerin.gameru.net/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=94.141.39.153&amp;*"/>
		<link rel="alternate" type="text/html" href="http://stalkerin.gameru.net/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/94.141.39.153"/>
		<updated>2026-04-29T16:54:44Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.22.6</generator>

	<entry>
		<id>http://stalkerin.gameru.net/wiki/index.php?title=%D0%94%D0%B5%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%86%D0%B8%D1%8F_%D1%83%D1%80%D0%BE%D0%B2%D0%BD%D0%B5%D0%B9_%D0%B2_%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82_%D0%A1%D0%94%D0%9A</id>
		<title>Декомпиляция уровней в формат СДК</title>
		<link rel="alternate" type="text/html" href="http://stalkerin.gameru.net/wiki/index.php?title=%D0%94%D0%B5%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%86%D0%B8%D1%8F_%D1%83%D1%80%D0%BE%D0%B2%D0%BD%D0%B5%D0%B9_%D0%B2_%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82_%D0%A1%D0%94%D0%9A"/>
				<updated>2010-02-22T09:18:55Z</updated>
		
		<summary type="html">&lt;p&gt;94.141.39.153: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Для декомпиляции игровых карт в формат LevelEditor-a используется Конвертер от Бардака, входящий в пакет !X-ray Game asset tools pack.&lt;br /&gt;
&lt;br /&gt;
Пакет !X-ray Game asset tools pack качаем тут [http://stalkerin.gameru.net/modules.php?name=Downloads&amp;amp;d_op=getit&amp;amp;lid=288]. Обновление [http://stalkerin.gameru.net/modules.php?name=Downloads&amp;amp;d_op=getit&amp;amp;lid=348] ставим поверх пакета.&lt;br /&gt;
&lt;br /&gt;
=== Пошаговое руководство по декомпиляции: ===&lt;br /&gt;
&lt;br /&gt;
1. Распаковать утилиту Бардака в нужную папку&lt;br /&gt;
&lt;br /&gt;
2. Там находим и открываем любым текстовым редакором converter.ini в нем находим строчки:&lt;br /&gt;
 ; 2947+ (финалка включая обновления)&lt;br /&gt;
 [2947_config]:2945_config&lt;br /&gt;
 $game_data$ = c:\temp\1\gamedata.3312\&lt;br /&gt;
 $game_levels$ = c:\temp\1\gamedata.3312\levels\&lt;br /&gt;
-------------------------------------------------------------------------------------------------------&lt;br /&gt;
 ; 3456+ (Clear Sky включая обновления)&lt;br /&gt;
 [3456_config]:2947_config&lt;br /&gt;
 $game_data$ = c:\temp\1\gamedata.3502\&lt;br /&gt;
 $game_levels$ = c:\temp\1\gamedata.3502\levels\&lt;br /&gt;
 fake_mu_gamemtls = 34xx_fake_mu_gamemtls&lt;br /&gt;
 fake_gamemtls = 34xx_fake_gamemtls&lt;br /&gt;
Тут $game_data$-путь до gamedata и $game_levels$-до папки levels в gamedata соответственно. Указываем правильные пути.&lt;br /&gt;
&lt;br /&gt;
3. Находим fsconverter.ltx там находим строчку :&lt;br /&gt;
 $sdk_root$ = false| false| c:\program files\x-ray sdk\level_editor\&lt;br /&gt;
где $sdk_root$ путь до полного СДК(покоцанный не работает нормально с этой утилитой)то есть после строчек false| false| пишем полный путь и именно со строчкой level_editor\ в конце как на примере(многие забывают).&lt;br /&gt;
&lt;br /&gt;
4. Ну вот конвертер полностью настроен теперь ключ для конвертирования в формат СДК:&lt;br /&gt;
Для этого создаем текстовой файл в него вписываем этот параметр и меняем формат(переименованием)с .txt на .bat.&lt;br /&gt;
converter -level &amp;lt;имя_карты&amp;gt; -out &amp;lt;имя_сцены&amp;gt; -mode le&lt;br /&gt;
pause&lt;br /&gt;
где &amp;lt;имя_карты&amp;gt; точное название папки с картой пример:l08_yantar(локация янтарь из ТЧ), &amp;lt;имя_сцены&amp;gt; то как карта будет назваться после конвертирования, можно не писать в этом случае карта будет называться также как и до конвертирования в нашем случае l08_yantar, ну и ключ mode в нашем примере le то есть конвертирование карты в формат СДК,также можно использовать ключи maya(Конвертирование геометрии в формат Майи), le2(Формат использующийся для карты l12_stancia_2(может быть еще для каких не проверял)), raw(Опять же формат СДК но уже в отладочном режиме).&lt;br /&gt;
&lt;br /&gt;
5. Если все сделано правильно после запуска батника пойдет процесс декомпиляции.&lt;br /&gt;
&lt;br /&gt;
6. Найти карту можно будет по адресу $sdk_root$\maps-фаил читаемый СДК и $sdk_root$\rawdata\objects\levels обьекты используемые данным уровнем.&lt;br /&gt;
&lt;br /&gt;
[[Категория:SDK]]&lt;/div&gt;</summary>
		<author><name>94.141.39.153</name></author>	</entry>

	<entry>
		<id>http://stalkerin.gameru.net/wiki/index.php?title=%D0%A0%D0%B0%D0%B1%D0%BE%D1%82%D0%B0_%D1%81_all.spawn</id>
		<title>Работа с all.spawn</title>
		<link rel="alternate" type="text/html" href="http://stalkerin.gameru.net/wiki/index.php?title=%D0%A0%D0%B0%D0%B1%D0%BE%D1%82%D0%B0_%D1%81_all.spawn"/>
				<updated>2010-02-22T09:17:21Z</updated>
		
		<summary type="html">&lt;p&gt;94.141.39.153: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Расспаковка all.spawn ==&lt;br /&gt;
&lt;br /&gt;
Для того, чтобы распаковать ол спавн, нам потребуется acdc. Для каждой версии игры нам понадобиться свой. Я описываю для ЗП ( во&lt;br /&gt;
всех частях сталкера этот процесс идентичен), поэтому и пользуюсь acdc от ЗП. Для того, чтобы запустить acdc нам будет &lt;br /&gt;
нужен ActivePerl (нужная версия входит в архив)Качаем acdc для ЗП [http://narod.ru/disk/17377026000/ACDC%20Cop.rar.html здесь].После того, как вы скачали acdc, установите эктивперл(если вы этого еще не сделали). Распакуйте acdc и скопируйте в эту папку свой all.spawn. Запустите .bat файл decompile(если его нет, то откройте блокнот, запишите в нем такие строки:&lt;br /&gt;
 perl acdccop.pl -d all.spawn&lt;br /&gt;
 pause&lt;br /&gt;
&lt;br /&gt;
И сохраните под именем &amp;quot;decompile.bat&amp;quot; Запускайте батник. Через некоторое время появятся .ltx файлы.&lt;br /&gt;
Все, ол спавн распакован и ждет шаманства над собой :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Структура файлов ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим структуру файлов. Файлы типа alife_ - это основные файлы, в которых содержаться секции спавна. Файлы типа way_ - это и есть &amp;quot;вэй&amp;quot;. Сквады, логика и прочая дребедень. Трогать мы их не будем.&lt;br /&gt;
Откроем любой alife_ файл и увидим там много секций спавна. Вот одна из них:&lt;br /&gt;
&lt;br /&gt;
 [0]&lt;br /&gt;
 ; cse_abstract properties&lt;br /&gt;
 section_name = breakable_object&lt;br /&gt;
 name = meshes\brkbl#0.ogf&lt;br /&gt;
 position = -160.539749145508,21.5325393676758,-195.387329101563&lt;br /&gt;
 direction = -0.00700339116156101,-0.108852192759514,0.412739604711533&lt;br /&gt;
 ; cse_alife_object properties&lt;br /&gt;
 game_vertex_id = 0&lt;br /&gt;
 distance = 0&lt;br /&gt;
 level_vertex_id = 293223&lt;br /&gt;
 object_flags = 0xffffffba&lt;br /&gt;
 ; cse_visual properties&lt;br /&gt;
 visual_name = meshes\brkbl#0&lt;br /&gt;
 ; cse_alife_object_breakable properties&lt;br /&gt;
 health = 1&lt;br /&gt;
&lt;br /&gt;
А теперь подробнее&lt;br /&gt;
&lt;br /&gt;
 [0] - уникальный &amp;quot;id&amp;quot;, то бишь номер секции&lt;br /&gt;
 ; cse_abstract properties - комментарий&lt;br /&gt;
 section_name = breakable_object - название секции( НЕ В КОЕМ СЛУЧАЕ НЕ СТАВТЕ ЗДЕСЬ СВОЕ НАЗВАНИЕ, ИНАЧЕ all.spawn ВЫ НЕ ЗАПАКУЕТЕ)&lt;br /&gt;
 name = meshes\brkbl#0.ogf - тоже название... Тут уже что годно можно написать&lt;br /&gt;
 position = -160.539749145508,21.5325393676758,-195.387329101563 - позиция на которой будет спавн&lt;br /&gt;
 direction = -0.00700339116156101,-0.108852192759514,0.412739604711533 - направление. В какую сторону &amp;quot;смотрит&amp;quot; обьект.&lt;br /&gt;
 ; cse_alife_object properties - комментарий&lt;br /&gt;
 game_vertex_id = 0 - вертикс.&lt;br /&gt;
 distance = 0&lt;br /&gt;
 level_vertex_id = 293223 - тоже вертикс. (зачем они объяснять не буду)&lt;br /&gt;
 object_flags = 0xffffffba - флаги обьекта. тоже рассматривать не будем&lt;br /&gt;
 ; cse_visual properties - комментарий&lt;br /&gt;
 visual_name = meshes\brkbl#0 - визуал.&lt;br /&gt;
 ; cse_alife_object_breakable properties - комментарий.&lt;br /&gt;
 health = 1 - здоровье.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Файл all.ltx - это список файлов, которые упакованы в ол спавн.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Создаем новую секцию спавна ==&lt;br /&gt;
Ну вот, самое интересное начинается )&lt;br /&gt;
Открываем любой файл. Я буду спавнить свои объекты, на новой локации. &lt;br /&gt;
&lt;br /&gt;
Допустим, нам нужно заспавнить сталкера. &lt;br /&gt;
Создаем секцию спавна. ( ВНИМАНИЕ! ПРЕЖДЕ ЧЕМ СПАВНИТЬ СТАЛКЕРА, ЕГО НУЖНО СОЗДАТЬ). Как описывать новых напсано [http://stalkerin.gameru.net/wiki/index.php/%D0%A0%D0%B5%D0%B4%D0%B0%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_NPC здесь]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 [20927] - уникальный номер секции&lt;br /&gt;
 ; cse_abstract properties - коментарий :) &lt;br /&gt;
 section_name = stalker - название секции. Если спавните сталкера - stalker. Своих названий быть не должно.&lt;br /&gt;
 name = marsh_koster_stalker - имя.  я использую имя профиля, которого вы создавали при создании нпс&lt;br /&gt;
 position = -150.17852783203,0.63608288764954,-293.19580078125 - координаты.&lt;br /&gt;
 direction = 0.062321275472641,0.00316426996141672,0.0140644172206521 - направление. Куда сталкер будет смотреть.&lt;br /&gt;
 ; cse_alife_trader_abstract properties - &lt;br /&gt;
 money = 5000 - деньги )&lt;br /&gt;
 character_profile = marsh_koster_stalker - профиль, который вы указали при создании нпс. Вот тут нужно указывать его&lt;br /&gt;
 ; cse_alife_object properties&lt;br /&gt;
 game_vertex_id = 934 - вертикс локации&lt;br /&gt;
 distance = 4.90000009536743 - дистанция, зачем нужна не знаю.&lt;br /&gt;
 level_vertex_id = 1418 - вертикс локации )&lt;br /&gt;
 object_flags = 0xffffffbf&lt;br /&gt;
 custom_data = &amp;lt;&amp;lt;END - кастом дата. Очень важный элемент при создании нпс. Проще говоря - логика.&lt;br /&gt;
 cfg = scripts/marsh/koster.ltx - путь к конфигу кастом даты&lt;br /&gt;
 [smart_terrains] - смарт террайны ( не рассматриваться)&lt;br /&gt;
 END - окончание кастом даты&lt;br /&gt;
 ; cse_alife_creature_abstract properties&lt;br /&gt;
 g_team = 0&lt;br /&gt;
 g_squad = 1&lt;br /&gt;
 g_group = 5&lt;br /&gt;
 health = 1&lt;br /&gt;
 dynamic_out_restrictions =&lt;br /&gt;
 dynamic_in_restrictions =&lt;br /&gt;
 (зачем нужно это не совсем понимаю, но заполнять так же, как и в основной секции)&lt;br /&gt;
 upd:health = 1&lt;br /&gt;
 upd:timestamp = 0x2009656c&lt;br /&gt;
 upd:creature_flags = 0x3d&lt;br /&gt;
 upd:position = -150.17852783203,0.63608288764954,-293.19580078125&lt;br /&gt;
 upd:o_model = 0&lt;br /&gt;
 upd:o_torso = 0.00316426996141672,0.062321275472641,0&lt;br /&gt;
 upd:g_team = 0&lt;br /&gt;
 upd:g_squad = 1&lt;br /&gt;
 upd:g_group = 5&lt;br /&gt;
 ; cse_alife_monster_abstract properties&lt;br /&gt;
 upd:next_game_vertex_id = 65535&lt;br /&gt;
 upd:prev_game_vertex_id = 65535&lt;br /&gt;
 upd:distance_from_point = 0&lt;br /&gt;
 upd:distance_to_point = 0&lt;br /&gt;
 ; cse_alife_human_abstract properties&lt;br /&gt;
 predicate5 = 1,1,0,0,1&lt;br /&gt;
 predicate4 = 2,2,0,2&lt;br /&gt;
 ; cse_ph_skeleton properties&lt;br /&gt;
 upd:start_dialog =&lt;br /&gt;
 ; se_stalker properties&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Сохраняем. Запаковываем ол спавн, файлом comlite.bat.&lt;br /&gt;
&lt;br /&gt;
В папке gamedata создаем папку spawns и копируем файл new.spawn(он будет называться именно так). Потом переименовываем в all.spawn.&lt;br /&gt;
&lt;br /&gt;
Статья не закончена и будет пополняться время от времени. Для начала хватит. &lt;br /&gt;
&lt;br /&gt;
Автор статьи - '''Andrey K aka f0rest'''&lt;/div&gt;</summary>
		<author><name>94.141.39.153</name></author>	</entry>

	<entry>
		<id>http://stalkerin.gameru.net/wiki/index.php?title=%D0%9A%D0%B0%D0%BA_%D0%BF%D0%B8%D1%81%D0%B0%D1%82%D1%8C_%D1%81%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D1%8B,_%D0%BD%D0%B5_%D0%BF%D1%80%D0%B8%D0%B2%D0%BE%D0%B4%D1%8F%D1%89%D0%B8%D0%B5_%D0%BA_%D0%B2%D1%8B%D0%BB%D0%B5%D1%82%D0%B0%D0%BC_%D0%B8_%D0%B1%D0%BE%D1%8E_%D1%81%D0%B5%D0%B9%D0%B2%D0%BE%D0%B2_(%D1%87%D0%B0%D1%81%D1%82%D1%8C_2)</id>
		<title>Как писать скрипты, не приводящие к вылетам и бою сейвов (часть 2)</title>
		<link rel="alternate" type="text/html" href="http://stalkerin.gameru.net/wiki/index.php?title=%D0%9A%D0%B0%D0%BA_%D0%BF%D0%B8%D1%81%D0%B0%D1%82%D1%8C_%D1%81%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D1%8B,_%D0%BD%D0%B5_%D0%BF%D1%80%D0%B8%D0%B2%D0%BE%D0%B4%D1%8F%D1%89%D0%B8%D0%B5_%D0%BA_%D0%B2%D1%8B%D0%BB%D0%B5%D1%82%D0%B0%D0%BC_%D0%B8_%D0%B1%D0%BE%D1%8E_%D1%81%D0%B5%D0%B9%D0%B2%D0%BE%D0%B2_(%D1%87%D0%B0%D1%81%D1%82%D1%8C_2)"/>
				<updated>2010-02-22T09:15:11Z</updated>
		
		<summary type="html">&lt;p&gt;94.141.39.153: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория:Статьи участников]]&lt;br /&gt;
[[Категория:Скрипты]]&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[Как писать скрипты, не приводящие к вылетам и бою сейвов|Начало в первой части статьи]]&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Как безопасно использовать коллбэки и таймерные события =&lt;br /&gt;
&lt;br /&gt;
В скриптовом движке есть удобный способ реакции на события - использование коллбэков - процедурных вызовов, привязанных к определённым событиям в жизни игрового объекта - получению повреждений, спавну, смерти и т.д. и т.п. Это hit_callback, death_callback из xr_motivator и многие другие... Все моддеры очень широко и совершенно спокойно пользуются ими, совершенно забывая при этом о таком важном факте, что это - обработки реального времени, как и таймерные события. Что это значит? А собственно вот что... Возьмём для примера коллбэк смерти неписей, мою головную боль последнего времени:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;xr_motivator.script -&lt;br /&gt;
function motivator_binder:death_callback(victim, who)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Это функция обрабатывает смерть неписей. Когда вызывается этот коллбек он начинает по очереди вызывать внутренние функции, расположенные в других модулях. Они разрегистрируют умершего непися в гулагах, спавнят в него лут, обновляют статистику, отключают его от доп. схем логики и т.д.&lt;br /&gt;
&lt;br /&gt;
Так вот, обычно, когда в функциях возникает конфликт параметров, бесконечный цикл, попытка индексации nil и т.д., функция вылетает со стандартным логом. '''Но только не в случае, когда она находится внутри коллбэка. Если функция внутри него, то в случае возникновении в ней любой нештатной ситуации, коллбэк наглухо виснет.''' Это происходит из-за того, что функции вызываются строго друг за другом, и каждая из них вызывается только тогда, когда её предшественница вернула управление коллбэку. В случае с death_callback опознать такого непися очень просто - в его трупе окажется фонарик, КПК и возможно ещё немного разных &amp;quot;мусорных&amp;quot; вещей, что говорит о том, что обработка его смерти повисла не дойдя даже до спавна лута. В подобной ситуации можно быть на 100% уверенным, что труп этот не был корректно разрегистрирован, и игра всё ещё считает его живым неписем. Кроме того, зависший коллбэк не освобождает стек (а он у Луа-подсистемы единый на все скрипты), что '''в итоге приводит к вылетам игры с переполнением памяти (вот она, реальная причина этих &amp;quot;родных&amp;quot; вылетов).''' Но было бы слишком хорошо, если бы всё ограничивалось этим... однако тут всё намного хуже... такие &amp;quot;зависшие&amp;quot; коллбэки, особенно если их произошло несколько подряд, очень серьёзно влияют на работу а-лайфа. В лучшем случае они, забивая, стек, мешают нормально работать схемам логики, в худшем вызывают зависания самого  а-лайфа (этот эффект, кстати, производят и сами трупы таких неписей, так как они, как мы помним, не разрегистрировались корректно). '''Основной итог таких событий - бой сейвов, сделанных после возникновения таких ситуаций.''' Если повис один коллбэк, то такие сейвы ещё через раз загружаются, если же несколько, и остановилась работа а-лайфа - всё, сейвы бьются наглухо и реанимации не подлежат.&lt;br /&gt;
&lt;br /&gt;
Поэтому, чтобы избежать такого развития событий, каждый раз, когда вы вносите в коллбэк новую функцию - проверьте её самым тщательным образом. Она не должна содержать никаких рекурсивных циклов, в ней обязательно должны быть проверки на валидность обрабатываемых объектов и значений, и обязательно должна быть обработка нештатных ситуаций - т.е. функция должна обязательно, в абсолютно любой ситуации вернуть управление коллбэку, так или иначе. В самом наихудшем случае - делайте как делали разработчики игры - вставляйте принудительный вылет на рабстол функцией abort - она позволяет передавать отладочное сообщение, и это всяко лучше чем незаметный бой сейвов. Если обработка оборвалась в самом начале, а ф-ция обязательно должна вернуть значение - заведите ей &amp;quot;безопасное&amp;quot; возвращаемое значение по-умолчанию, которое она будет выдавать, если всё пошло плохо. И никогда не пренебрегайте пошаговой отладкой коллбэков с выводом в лог, особенно когда пишете схемы логики - это критически важно для стабильности вашего мода.&lt;br /&gt;
&lt;br /&gt;
== Основные внутриигровые признаки зависания коллбэков типа hit_callback, death_callback ==&lt;br /&gt;
&lt;br /&gt;
1. В трупах попадаются фонарики, КПК, разный мусор и общий лут слишком богат.&lt;br /&gt;
&lt;br /&gt;
2. Частые вылеты во время интенсивных боёв с логами типа&lt;br /&gt;
    Sheduler tried to update object...&lt;br /&gt;
    smart_terrain:1145(1146)&lt;br /&gt;
    LUA: out of memory&lt;br /&gt;
    любой_модуль_логики:любая_cтрока - stack overflow&lt;br /&gt;
&lt;br /&gt;
3. Частые &amp;quot;родные&amp;quot; вылеты в момент смерти непися или попадания по нему&lt;br /&gt;
&lt;br /&gt;
4. Произвольно бьются сейвы во время сражений, выброса и других насыщенных действиями событий&lt;br /&gt;
&lt;br /&gt;
= Использование защищённого кода в LUA =&lt;br /&gt;
&lt;br /&gt;
Периодически случаются такие ситуации, когда мы можем получить вылет при проверке аргумента, и не можем его адекватно заизолировать с помощью предварительной проверки на валидность значения. Вот простой пример: когда я отлаживал '''death_callback''' неписей, я периодически сталкивался с тем, что обращение к методу '''smart_terrain_id()''' при смерти непися иногда вызывало вылет &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;smart_terrain:1143 &amp;quot;attempt to index a nil value&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
- хотя это свойство является родным методом объекта, и отсутствовать напрочь никак не может. В итоге я пришёл к выводу, что его просто иногда не успевает отработать движок, так как вылет этот проявлялся в основном в интенсивных боях и совершенно произвольно.&lt;br /&gt;
&lt;br /&gt;
Вот код, в котором происходил вылет:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code lua&amp;gt;function on_death( obj_id )&lt;br /&gt;
--	printf( &amp;quot;on_death obj_id=%d&amp;quot;, obj_id )&lt;br /&gt;
&lt;br /&gt;
	local sim = alife()&lt;br /&gt;
&lt;br /&gt;
	if sim then&lt;br /&gt;
		local obj     = sim:object( obj_id )&lt;br /&gt;
		local strn_id = obj:smart_terrain_id()  --- вылет происходит тут&lt;br /&gt;
&lt;br /&gt;
		if strn_id ~= 65535 then&lt;br /&gt;
			sim:object( strn_id ).gulag:clear_dead(obj_id)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Это кусок родного кода из версии 1,0005 игры. Я долго пытался разными способами отсечь этот вылет, вводя предварительные проверки, однако это совершенно ничего не давало - вылет всё равно периодически случался, так как проверки эти сами его вызывали. Тогда я зарылся в документацию по Lua и обнаружил замечательную родную базовую функцию, введённую ещё с первых версий Lua, которой почему-то не пользовались ни разработчики игры, ни моддеры (хотя сама она в Lua сталкера присутствует, и работает отлично, без каких-либо нареканий). Вот она:&lt;br /&gt;
&lt;br /&gt;
'''pcall (f, arg1, ···)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Вызывает функцию f с указанными через запятую аргументами в защищённом режиме. Это означает, что любая ошибка, даже критическая, внутри вызванной функции, не передаётся наружу - вызывавшей подсистеме. Вместо этого '''pcall''' перехватывает ошибку и возвращает код статуса. Первая возвращаемая переменная это сам код, (true или false) и если всё прошло хорошо, он равен true. В этом случае '''pcall''' сразу после статуса возвращает все результаты от работы защищённой им функции. Если же в защищённой функции произошла ошибка, то '''pcall''' вернёт false и затем сообщение об ошибке. (Обратите внимание, обработка ошибки присходит БЕЗ вылета! Вместо вылета вы получите вполне адекватную строку с ошибкой, которую можно вывести в лог для последующей обработки)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Я настоятельно советую пользоваться этой функцией в случаях, когда из коллбэков вызываются сложные комплексные обработки, вроде обработки из менеджера вооружений AI-пака. Это позволяет предотвратить как вылеты, так и зависания обработок, и в итоге позволяет хорошо стабилизировать игру.&lt;br /&gt;
&lt;br /&gt;
Возвращаясь к нашим смарттеррейнам... вот как в итоге я подавил вылет типа smart_terrain:1143 с помощью pcall:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code lua&amp;gt;--- эта функция пытается проверить св-во smart_terrain_id объекта. Именно её мы вызовем в защищённом режиме.&lt;br /&gt;
function prot_smt_td(obj)&lt;br /&gt;
	if IsStalker(obj) or IsMonster(obj) then&lt;br /&gt;
		return obj:smart_terrain_id()&lt;br /&gt;
	else	&lt;br /&gt;
		return 65535&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function on_death( obj_id )&lt;br /&gt;
--	printf( &amp;quot;on_death obj_id=%d&amp;quot;, obj_id )&lt;br /&gt;
	local sim = alife()&lt;br /&gt;
	if sim then&lt;br /&gt;
		local obj = sim:object( obj_id )&lt;br /&gt;
		if obj then&lt;br /&gt;
			local strn_id = 65535  --- предварительно проинитим переменную, на &lt;br /&gt;
						--- случай если у нас prot_smt_td выдаст ошибку&lt;br /&gt;
			local result, smt_id = pcall(prot_smt_td,obj)	--- вызываем prot_smt_td в защищённом режиме &lt;br /&gt;
									--- и сразу присваиваем его вывод переменным&lt;br /&gt;
			if result then --- если pcall выдало true&lt;br /&gt;
				strn_id = smt_id  --- тогда применяем полученное значение&lt;br /&gt;
			end&lt;br /&gt;
			--- если же обработка выдаст ошибку, то strn_id останется неизменным...&lt;br /&gt;
			if strn_id ~= 65535 then&lt;br /&gt;
				sim:object(strn_id).gulag:clear_dead(obj_id)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В других местах это делается совершенно аналогично. Подробнее об этой и многих других функция для контроля кода, незаслуженно игнорируемых большинством моддеров, можно почитать тут: http://lua-users.org/wiki/FinalizedExceptions - на английском правда, но захотите - разберётесь, там всё просто. &lt;br /&gt;
&lt;br /&gt;
Настоятельно советую вам изучить работу кода в таких условиях и научиться его правильно применять - этим вы сильно облегчите жизнь как себе, так и тем, кто после вас будет рыться в вашем коде или импортировать его в свои разработки.&lt;br /&gt;
&lt;br /&gt;
= Скрытые критические проблемы в обработке вылетов игрой =&lt;br /&gt;
&lt;br /&gt;
Ведя на днях отладку, выяснил в чём проблема с периодическим боем сейвов и многими другими заморочками как в оригинале игры, так и во многих модах... дело, как выяснилось, далеко не всегда в кривых руках. Существует есть такая стандартная ф-ция '''abort''' - предназначенная для выкидывания из игры, если что-то пошло не так. И как оказалось, она срабатывает далеко не всегда. Выяснилось это следующим образом:&lt;br /&gt;
&lt;br /&gt;
В одном из логов нашего бета-тестера я увидел '''стандартное сообщение о вылете внутри рабочего лога'''... да-да, то самое которое '''FATAL ERROR''' и дальше по тексту. При этом игра у него НЕ вылетала, это сообщение об ошибке мы обнаружили позже, по случайности. Я заподозрил, что что-то не в порядке, и вставил внутрь этой ф-ции контрольную метку, кидавшую в консоль сообщение, в котором содержался паттерн сообщения об ошибке и само сообщение. Так вот, оказалось, что эта самая функция '''abort''' вызывается в игре с завидным постоянством (вы удивитесь насколько часто), когда возникают исключения в схемах логики, звука и т.д., но игра от этого вылетает на рабочий стол '''максимум только 3 раза из 10 вызовов'''. Вылет НЕ происходит обычно, когда функции передан паттерн ошибки, а остальные параметры пустые, такое бывает, и частенько. И если не сделать внутри этой функции особой метки для вывода в лог, как сделал это я, её вызовы проходят совершенно незаметно, и '''игра после критических ошибок продолжается как ни в чём ни бывало.''' А приводит это вот к чему... Внутри '''xr_logic''' в процедуре записи пстора (хранилища логики и флагов) неписей есть вызовы этого самого аборта в случае если на запись в пстор передана некорректная величина. Ну а так как аборт периодически вообще не срабатывает, то часто попадается ситуация, что неписям в пстор пишется полный ахтунг: куски кода из ОЗУ, всякая муть из лтх-ов, куски аллспавна, всё что угодно. Происходит это оттого, что кодер, писавший эту функцию ('''xr_logic.pstor_store(obj, varname, val)'''), явно и думать не думал что '''abort''' может не сработать. У него запись в пстор стояла после проверки, а не внутри неё (very bad idea), и если abort не срабатывал, игра писала в пстор мусор совершенно спокойно и незаметно для игрока. Потом вся эта хрень попадала прямо в сейвы. Вот проблемный код для наглядности:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code lua&amp;gt;function pstor_store(obj, varname, val)&lt;br /&gt;
	local npc_id = obj:id()&lt;br /&gt;
	if db.storage[npc_id].pstor == nil then&lt;br /&gt;
		db.storage[npc_id].pstor = {}&lt;br /&gt;
	end&lt;br /&gt;
	local tv = type(val)&lt;br /&gt;
	if not pstor_is_registered_type(tv) then&lt;br /&gt;
		abort(&amp;quot;xr_logic: pstor_store: not registered type '%s' encountered&amp;quot;, tv) --- вот тут мы должны если что вылететь&lt;br /&gt;
	end&lt;br /&gt;
	db.storage[npc_id].pstor[varname] = val -- а если не вылетели, всё, получим запись в пстор левой мути&lt;br /&gt;
end&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Разумеется игра этим пстором в итоге давится, и сейвы сделанные после такой милой записи практически лопаются. Результат - &amp;quot;битые&amp;quot; (на самом деле подлежат реанимации) сейвы. Происходит это потому, что игра из сейва грузит неписям псторы сплошным чтением по словам, пока они не закончатся. В случае же если в псторе обнаруживается записанный ранее мусор, то обработка либо вылетает сразу, либо наглухо виснет, пытаясь запихать эдак с миллион слов в пстор особо отличившегося непися. Как вам например непись с размером пстора в 1697451 слова? В результате попытки его обработать игра просто на стадии синхронизации выжрала всю доступную ОЗУ и повисла. &lt;br /&gt;
&lt;br /&gt;
Решение этой проблемы оказалось достатоно простым: во-первых я предположил максимальный размер полезной части пстора неписей в 20 слов r_u32() (пока ориентировочно, я ещё уточняю эту величину), и соответственно сделал остановку цикла загрузки пстора для неписей через 20 итераций. Там же, где в цикле стояла проверка на валидность записываемых данных (кстати тоже с вылетом в случае провала проверки), я сделал так, что если параметр не относится к валидному типу данных, то запись параметра в пстор не производится совсем. Это необходимо для того, чтобы если вдруг в сейве обнаружится мусор, то он был бы просто отброшен обработкой. Практика показала, что в итоге такие неписи вполне адекватны и в дальнейшем никаких проблем не вызывают, так как начало их пстора, с нормальными данными, обычно не повреждается - мусор дописывается после них, а не вместо них. &lt;br /&gt;
&lt;br /&gt;
Ну и во-вторых модифицировал запись параметров в пстор, просто убрав запись под основание if-else так, чтобы если параметр неверен, он не записывался совсем. Теперь кстати, очень интересно, сохранились ли те же заморочки с ф-цией '''abort''' в Чистом Небе, и если да, то останутся ли в Зове Припяти?&lt;br /&gt;
&lt;br /&gt;
------------&lt;br /&gt;
&lt;br /&gt;
== Необходимые для стабилизации игры правки в модулях ==&lt;br /&gt;
&lt;br /&gt;
'''Эта правка предотвращает запись в пстор если не сработал аборт:'''&lt;br /&gt;
&lt;br /&gt;
''xr_logic.script''&lt;br /&gt;
&lt;br /&gt;
'''Было:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code lua&amp;gt;function pstor_store(obj, varname, val)&lt;br /&gt;
	local npc_id = obj:id()&lt;br /&gt;
	if db.storage[npc_id].pstor == nil then&lt;br /&gt;
		db.storage[npc_id].pstor = {}&lt;br /&gt;
	end&lt;br /&gt;
	local tv = type(val)&lt;br /&gt;
	if not pstor_is_registered_type(tv) then&lt;br /&gt;
		abort(&amp;quot;xr_logic: pstor_store: not registered type '%s' encountered&amp;quot;, tv)&lt;br /&gt;
	end&lt;br /&gt;
	db.storage[npc_id].pstor[varname] = val&lt;br /&gt;
end&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Стало:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code lua&amp;gt;function pstor_store(obj, varname, val)&lt;br /&gt;
	if not obj then return end&lt;br /&gt;
	local npc_id = obj:id()&lt;br /&gt;
	if db.storage[npc_id].pstor == nil then&lt;br /&gt;
		db.storage[npc_id].pstor = {}&lt;br /&gt;
	end&lt;br /&gt;
	local tv = type(val)&lt;br /&gt;
	if not pstor_is_registered_type(tv) then&lt;br /&gt;
		dgblog(&amp;quot;xr_logic: pstor_store: not registered type encountered - write in pstor_store cancelled&amp;quot;)&lt;br /&gt;
		-- abort убран, так как один хрен не работает. Пусть тогда хотя бы в лог что-то валится.&lt;br /&gt;
	else&lt;br /&gt;
		db.storage[npc_id].pstor[varname] = val&lt;br /&gt;
		-- вот так и только так. Если значение не валидно, ничего не происходит.&lt;br /&gt;
	end	&lt;br /&gt;
end&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''А эта правка выкинет из пстора весь мусор при загрузке сейва, если он как-то в него попал'''&lt;br /&gt;
&lt;br /&gt;
'''Было:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code lua&amp;gt;function pstor_load_all(obj, reader)&lt;br /&gt;
	local npc_id = obj:id()&lt;br /&gt;
	local pstor = db.storage[npc_id].pstor&lt;br /&gt;
	if not pstor then&lt;br /&gt;
		pstor = {}&lt;br /&gt;
		db.storage[npc_id].pstor = pstor&lt;br /&gt;
	end&lt;br /&gt;
	local ctr = reader:r_u32()&lt;br /&gt;
	for i = 1, ctr do&lt;br /&gt;
		local varname = reader:r_stringZ()&lt;br /&gt;
		local tn = reader:r_u8()&lt;br /&gt;
		if tn == pstor_number then&lt;br /&gt;
			pstor[varname] = reader:r_float()&lt;br /&gt;
		elseif tn == pstor_string then&lt;br /&gt;
			pstor[varname] = reader:r_stringZ()&lt;br /&gt;
		elseif tn == pstor_boolean then&lt;br /&gt;
			pstor[varname] = reader:r_bool()&lt;br /&gt;
		else&lt;br /&gt;
			abort(&amp;quot;xr_logic: pstor_load_all: not registered type N %d encountered&amp;quot;, tn)&lt;br /&gt;
		end&lt;br /&gt;
		printf(&amp;quot;_bp: pstor_load_all: loaded [%s]='%s'&amp;quot;, varname, utils.to_str(pstor[varname]))&lt;br /&gt;
	end&lt;br /&gt;
end&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Стало:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code lua&amp;gt;function pstor_load_all(obj, reader)&lt;br /&gt;
	local npc_id = obj:id()&lt;br /&gt;
	local pstor = db.storage[npc_id].pstor&lt;br /&gt;
	if not pstor then&lt;br /&gt;
		pstor = {}&lt;br /&gt;
		db.storage[npc_id].pstor = pstor&lt;br /&gt;
	end&lt;br /&gt;
	local ctr = reader:r_u32()&lt;br /&gt;
	if tonumber(ctr) &amp;gt; 20 and tostring(obj:name()) ~= &amp;quot;single_player&amp;quot; and npc_id ~= db.actor:id() then&lt;br /&gt;
		-- максимум 20 итераций - это число ещё уточняется, возможно понадобится больше&lt;br /&gt;
                -- если у вас в пстор что-то свое пишется, ориентируйтесь на свои значения&lt;br /&gt;
		-- и обязательно убираем из проверки актора - у него очень толстый пстор, и к тому же&lt;br /&gt;
                -- если уж поврежденным будет его пстор, то тут точно уже ничего не поможет&lt;br /&gt;
		dgblog(&amp;quot;ОБНАРУЖЕН ОБЪЕКТ С ПОВРЕЖДЕННЫМ PSTOR: &amp;quot;..tostring(obj:name())..&lt;br /&gt;
&amp;quot; БУДЕТ ПРОИЗВЕДЕНА ПОПЫТКА ВОССТАНОВЛЕНИЯ&amp;quot;)&lt;br /&gt;
		ctr = 20 &lt;br /&gt;
	end&lt;br /&gt;
	for i = 1, ctr do&lt;br /&gt;
		local varname = reader:r_stringZ()&lt;br /&gt;
		local tn = reader:r_u8()&lt;br /&gt;
		if tn == pstor_number then&lt;br /&gt;
			pstor[varname] = reader:r_float()&lt;br /&gt;
		elseif tn == pstor_string then&lt;br /&gt;
			pstor[varname] = reader:r_stringZ()&lt;br /&gt;
		elseif tn == pstor_boolean then&lt;br /&gt;
			pstor[varname] = reader:r_bool()&lt;br /&gt;
		else&lt;br /&gt;
			-- не надо пытаться вылетать - просто не пишем поврежденные данные&lt;br /&gt;
			-- при этом обязательно удалять саму переменную - в результате записи&lt;br /&gt;
 			-- мусора в пстор одно только ее название может повесить загрузку&lt;br /&gt;
			pstor[varname] = nil&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Эти примеры приведены для чистой игры. Единственное в чем не уверен пока, это в том, что максимум полезного размера - 20 слов. Возможно нужно выделить больше, это надо будет проверить ещё экспериментальным путем...&lt;br /&gt;
&lt;br /&gt;
Кроме этого, советую ещё внутрь ф-ции abort вставить отладочные метки, чтобы точно знать когда она вызывалась. Настоятельно советую сделать это даже если вы матёрый моддер со стажем - гарантирую, будете неприятно удивлены.&lt;br /&gt;
&lt;br /&gt;
Я это сделал вот так:&lt;br /&gt;
&lt;br /&gt;
''_g.script''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code lua&amp;gt;-- Крешнуть игру (после вывода сообщения об ошибке в лог)&lt;br /&gt;
function abort(fmt, msg)&lt;br /&gt;
	local message = tostring(msg)&lt;br /&gt;
	dbglog(&amp;quot;ERROR PATTERN: &amp;quot;..tostring(fmt))&lt;br /&gt;
	dbglog(&amp;quot;ERROR REASON: &amp;quot;..message)&lt;br /&gt;
	local reason = string.format(fmt, message)&lt;br /&gt;
	assert(&amp;quot;ERROR: &amp;quot; .. reason)&lt;br /&gt;
	printf(&amp;quot;ERROR: &amp;quot; .. reason)&lt;br /&gt;
	dbglog(&amp;quot;%s&amp;quot;, reason)&lt;br /&gt;
	printf(&amp;quot;%s&amp;quot;)&lt;br /&gt;
end&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Другие частые проблемы =&lt;br /&gt;
&lt;br /&gt;
Спустя некоторое время я обнаружил причины ещё нескольких часто встречающихся вылетов, и решил записать их описание сюда - эта информация наверняка ещё много кому пригодится.&lt;br /&gt;
&lt;br /&gt;
== Вылеты при удалении объектов из игры ==&lt;br /&gt;
&lt;br /&gt;
При использовании для удаления объектов родной движковой функции '''alife():release(obj:id(), true)''' возможен целый ворох разнообразнейших вылетов, обычно - безлоговых, что сильно затрудняет их отладку. Вот из-за чего они возникают:&lt;br /&gt;
&lt;br /&gt;
1) Вылет при удалении непися или монстра.&lt;br /&gt;
   Решение: с помощью alife():release '''можно удалять только мёртвые объекты'''. Поэтому если вам нужно удалить с её помощью непися или монстра, его нужно убить любым доступным методом, хотя бы нанеся ему hit() с любым запредельным уроном по вкусу.&lt;br /&gt;
&lt;br /&gt;
2) Вылет при удалении оружия или артефакта.&lt;br /&gt;
   Решение: такая проблема часто встречается в случае если объект неудачно расположен или находится в руках у непися. Для того чтобы не произошло вылета, убедитесь что объект доступен как серверный перед удалением. Вот так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code lua&amp;gt;	local obj = alife():object(i)&lt;br /&gt;
	if obj then&lt;br /&gt;
		alife():release(obj, true)&lt;br /&gt;
	end&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Эту конструкцию вообще желательно использовать всегда, когда вы так удаляете объекты.&lt;br /&gt;
&lt;br /&gt;
3) Вылет при удалении аномалии.&lt;br /&gt;
   Решение: аномалии - очень капризные при подобном с ними обращении объекты. Они влияют на своё окружение, и если рядом с ними находится непись или монстр, то удаление такой аномалии приведёт к вылету игры. Чтобы этого не произошло, аномалию надо сначала выключить функцией '''disable_anomaly''', и удалять затем ТОЛЬКО тогда, когда она не будет занята влиянием на динамический объект. Для этого нужно получить список мобов на локации, и из их нетпакетов считать идентификаторы действующих на них рестрикторов. Если ваша аномалия будет в этом списке - удалять её нельзя. Дождитесь пока она освободится.&lt;br /&gt;
&lt;br /&gt;
== Вылет при открытии закладки &amp;quot;Контакты&amp;quot; в ПДА ==&lt;br /&gt;
&lt;br /&gt;
Простой безлоговый вылет при открытии закладки &amp;quot;Контакты&amp;quot;. Встречался во всех крупных модах, и никто не знал как его излечить. А лечится он банально - '''его причина - дублирование идентификаторов секций в XML-файле, описывающем иконки неписей для закладки &amp;quot;Контакты&amp;quot;'''. Нужно всего лишь проверить этот файл на наличие дублированных идентификаторов и удалить их. Вылет пропадёт и никогда больше не будет встречаться.&lt;br /&gt;
&lt;br /&gt;
== Вылеты при вызове несуществующих функций из XML ==&lt;br /&gt;
&lt;br /&gt;
В ХML-файлах, используемых для описания инфопоршенов, для многих инфопоршенов прописаны действия, которые игра вызывает при взятии этого инфопоршена. Вот так примерно:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code xml&amp;gt;&lt;br /&gt;
	&amp;lt;info_portion id=&amp;quot;barman_document_have&amp;quot;&amp;gt;&lt;br /&gt;
		&amp;lt;action&amp;gt;dialogs.set_actor_prebandit1&amp;lt;/action&amp;gt;&lt;br /&gt;
		&amp;lt;action&amp;gt;bar_spawn.bandits2&amp;lt;/action&amp;gt;&lt;br /&gt;
		&amp;lt;action&amp;gt;bar_spawn.bandits3&amp;lt;/action&amp;gt;&lt;br /&gt;
		&amp;lt;action&amp;gt;bar_spawn.bandit7&amp;lt;/action&amp;gt;&lt;br /&gt;
		&amp;lt;action&amp;gt;bar_spawn.bandit8&amp;lt;/action&amp;gt;&lt;br /&gt;
	&amp;lt;/info_portion&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Так вот, если вы допустите опечатку в названии вызываемой функции или же случайно её удалите - игра будет стабильно вылетать без лога при взятии этого инфопоршена.&lt;br /&gt;
&lt;br /&gt;
--[[Участник:Kamikazze|KamikaZze (OGSE Team)]] 11:04, 3 сентября 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
= Авторы =&lt;br /&gt;
Статья создана: [[Участник:Kamikazze|Kamikazze]]&lt;/div&gt;</summary>
		<author><name>94.141.39.153</name></author>	</entry>

	<entry>
		<id>http://stalkerin.gameru.net/wiki/index.php?title=%D0%A4%D0%BE%D1%80%D0%BC%D0%B0%D1%82_%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2_%D0%BF%D0%BE%D1%81%D1%82%D0%BF%D1%80%D0%BE%D1%86%D0%B5%D1%81%D1%81%D0%B8%D0%BD%D0%B3%D0%B0_(ppe)</id>
		<title>Формат файлов постпроцессинга (ppe)</title>
		<link rel="alternate" type="text/html" href="http://stalkerin.gameru.net/wiki/index.php?title=%D0%A4%D0%BE%D1%80%D0%BC%D0%B0%D1%82_%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2_%D0%BF%D0%BE%D1%81%D1%82%D0%BF%D1%80%D0%BE%D1%86%D0%B5%D1%81%D1%81%D0%B8%D0%BD%D0%B3%D0%B0_(ppe)"/>
				<updated>2010-02-22T09:06:14Z</updated>
		
		<summary type="html">&lt;p&gt;94.141.39.153: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Вступление==&lt;br /&gt;
&lt;br /&gt;
Представляю на суд общественности результаты моих изысканий по формату файлов постпроцессинга ('''.ppe''')&lt;br /&gt;
&lt;br /&gt;
Нераскрытыми для меня осталось 6 переменных (переменные, которые я для себя назвал free, обязательно идут перед каждой триадой цепочек, управляющих цветом и 3 коэффициента, идут в каждом правиле после байта функции), но простенькие '''ppe'''-файлы можно делать и без них.&lt;br /&gt;
&lt;br /&gt;
Вообще, оказалось, что возможности '''ppe''' были сильно мною переоценены (например тепловизор сделать с их помощью если и можно, то крайне проблематично). Основной недостаток - '''ppe''' можно применить только ко всему экрану, на отдельный обьект это не предусмотрено движком (даже стелс-режим кровососа реализуется подменой модели). Так что могу предложить только слегка улучшеный прибор ночного зрения.&lt;br /&gt;
&lt;br /&gt;
Получилось так себе, просто убрал шумы, добавил яркости/контрастности, но зато теперь со включенным nv днем не побегаешь - засветка почти как на настоящем (как в кино показывают) и туман гораздо сильнее мешает, клубы тумана почти непрозрачны.&lt;br /&gt;
&lt;br /&gt;
По поводу компилятора/декомпилятора, пришел к выводу, что фильтр постпроцесса изделие штучное, смысла в отдельных утилитах нет - я все анализировал, клепал, менял только с помощью блокнота и шестнадцатеричного редактора (кстати, выяснил, что при смене файла постпроцесса необязательно перезапускать сталкера и даже релоад делать ни к чему - изменения подхватываются при следующем выключении постпроцесса в данном случае nv).&lt;br /&gt;
&lt;br /&gt;
При анализе ppe сильно помог тот факт, что постпроцесс существует в игре в текстовом и компилированом виде (кому интересно, копайте '''\gamedata\script\postprocess.script''' - полный разбор текстовых файлов написан обычным скриптом, там же, в самом конце функция ''main'' загружает погоду и файл постпроцессинга, сами файлы лежат '''\gamedata\config\scripts''' например '''proba.ltx'''). Компилированные ppe лежат в anims.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Практика==&lt;br /&gt;
&lt;br /&gt;
Итак, '''ppe'''-файл - это набор правил, как должен изменяться тот или иной параметр изображения во времени, всего этих параметров - 16 (названия взяты из текстовых версий, чтобы путаницы не было). В отличие от текстовой версии, цепочки должны идти только в этом порядке и их всегда должно быть только 16 (если игра вывалилась с сообщением в логах ''noise.grain cannot be zer''o, значит вы что-то пропустили).&lt;br /&gt;
&lt;br /&gt;
Выбраная цветовая компонента умножается на коэффициент, то при параметре равным 1 чистый белый цвет останется белым, а чистый черный - черным, остальные приобретут компонентный оттенок.&lt;br /&gt;
&lt;br /&gt;
* '''free1'''	- об этой переменной чуть ниже&lt;br /&gt;
* '''color_add_red'''&lt;br /&gt;
* '''color_add_green'''&lt;br /&gt;
* '''color_add_blue'''&lt;br /&gt;
&lt;br /&gt;
Указанное значение принимается как база для данного цвета, то есть, если у данного пикселя значение цвета меньше указанного, то оно принимается как указанное, а если больше, то остается прежним. Следует заметить, что это единственный набор переменных, задирать значения в которых выше 0.5 не имеет смысла, 0.5 прибавляется где-то в дебрях движка.&lt;br /&gt;
&lt;br /&gt;
* '''free2'''&lt;br /&gt;
* '''color_base_red'''&lt;br /&gt;
* '''color_base_green'''&lt;br /&gt;
* '''color_base_blue'''&lt;br /&gt;
&lt;br /&gt;
Эта триада правил отвечает за вес цвета в сером/яркостном представлении и в обычном цветном режиме результат не виден. Но при увеличении правила '''gray''' становится ясно, что при например '''color_gray_red''' = -1 чисто красные компоненты становятся черными, 0 = остаются без изменений, 1 - чисто белыми:&lt;br /&gt;
&lt;br /&gt;
*'''free3'''&lt;br /&gt;
*'''color_gray_red'''&lt;br /&gt;
*'''color_gray_green'''&lt;br /&gt;
*'''color_gray_blue'''&lt;br /&gt;
&lt;br /&gt;
Переменная управляет величиной обратной насыщенности, то есть, чем больше gray (максимум +1) тем меньше насыщенность изображения:&lt;br /&gt;
&lt;br /&gt;
*'''gray'''&lt;br /&gt;
&lt;br /&gt;
Размытие изображения, при больших значениях (пробовал 25) начинаются косяки, портится нижняя часть, если долго стоять на месте:&lt;br /&gt;
&lt;br /&gt;
*'''blur'''&lt;br /&gt;
&lt;br /&gt;
Раздвоение изображения по горизонтали и вертикали соответственно. Значение указывается относительно экрана, то есть при 1 копии обьекта, первоначально находящегося в центре окажутся точно по краям:&lt;br /&gt;
&lt;br /&gt;
*'''duality_h'''&lt;br /&gt;
*'''duality_v'''&lt;br /&gt;
&lt;br /&gt;
*'''noise_intensity'''       - интенсивность шума&lt;br /&gt;
*'''noise_granularity'''     - размер зерна шума&lt;br /&gt;
*'''noise_fps  '''           - сколько раз в секунду шум должен пересчитываться&lt;br /&gt;
&lt;br /&gt;
Файл '''всегда''' начинается с '''01 00 00 00''' - скорее всего это синатура, по которой движок определяет содержимое(кстати, у файлов anm, которые содержать анимацию камеры и похоже имеют ту же логику строения, что и ppe сигнатурой является '''00 11 00 00''' ).&lt;br /&gt;
&lt;br /&gt;
Затем идет 4 байта неопределенной переменной, которую я для себя назвал free. Всего их 3. Эти переменные стоят только перед триадами, отвечающими за изменения цветов, обычно равны '''7C 00 00 00''', но есть небольшие вариации. Визуально определить, что меняется при изменении этой переменной я не смог, если кто совершит этот подвиг - вечная слава :)&lt;br /&gt;
&lt;br /&gt;
Затем начинаются цепочки в перечисленном выше порядке.&lt;br /&gt;
Цепочка начинается с '''01 01 ''ХХ'' 00''', где '''''ХХ''''' - число правил в данной цепочке. Если указано 01 01 00 00 (то есть цепочка с 0 правил, то данная цепочка в постпроцессинге не участвует и сразу после нее должна начинаться следующая цепочка). '''Основная ошибка, которую можно допустить - несоответствие реального числа правил с указаным в заголовке цепочки. Контроль, контроль, и еще раз контроль.'''&lt;br /&gt;
&lt;br /&gt;
Каждая цепочка состоит из правил изменения переменной. Исходя из скрипта разбора текстовых версий можно предположить, что правил в цепочке не должно быть больше 16 (хотя возможно это только для текстовых).Совершенно необязательно, что этих правил в разных цепочках будет одинаковое количество или даже длиться они будут одинаковое время.&lt;br /&gt;
&lt;br /&gt;
Правило содержит в себе всегда ровно 23 байта. Примерное описание - &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
9A 99 99 3E 00 00 A0 40 00 00 80 00 80 00 80 00 80 00 80 00 80 00 80&lt;br /&gt;
----------- ----------- -- ----- ----- ----- -----------------------&lt;br /&gt;
 значение      время    ф    k1    k2    k3                                   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*'''значение''' - 4-байтная float переменная, обычно меняется от -1 до +1&lt;br /&gt;
*'''время'''  - в секундах 4-байтная float переменная&lt;br /&gt;
*'''ф''' - функция, во всех ppe равна 00, но попробовал менять('''не должна быть 04 - игра вылетает'''). 00,03 - синус, 01,05 - косинус, 02 - линейная, остальные значения игнорируются и правило перестает работать вообще.&lt;br /&gt;
*'''k1, k2, k3''' - коэффициенты для функций вот с ними почти не разбирался, на линейную фунуцию изменений не выявил, на синус/косинус влияют очень сильно, но на поиск закономерности не хватило времени, по умолчанию равны 00 80 00 80 00 80&lt;br /&gt;
*остаток строки во всех файлах 00 80 00 80 00 80 00 80 - изменение визуально ничего не меняет, возможно зарезервировано для следующих версий.&lt;br /&gt;
&lt;br /&gt;
Вот и все. Поле для работы как видите еще есть - коэффициенты k[1,2,3] и переменные free[1,2,3] - предлагаю общественности устроить мозговой штурм на них. &lt;br /&gt;
&lt;br /&gt;
Напоследок мой файл ночного зрения с комментариями (для использования комменты удалить, шестнадцатиричный код загнать в WinHex и сохранить как '''anims\x.ppe'''(имя любое), и не забыть поправить '''config\misc\postprocess.ltx''' в нужной секции).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
01 00 00 00 		// сигнатура&lt;br /&gt;
&lt;br /&gt;
// Цвета выкручиваем на максимум&lt;br /&gt;
7C 00 00 00 		// free1&lt;br /&gt;
01 01 02 00 		// color_add_red&lt;br /&gt;
00 00 80 3F 00 00 00 00 00 00 80 00 80 00 80 00 80 00 80 00 80 00 80 &lt;br /&gt;
00 00 80 3F 00 00 00 41 00 00 80 00 80 00 80 00 80 00 80 00 80 00 80 &lt;br /&gt;
01 01 02 00 		// color_add_green&lt;br /&gt;
00 00 80 3F 00 00 00 00 00 00 80 00 80 00 80 00 80 00 80 00 80 00 80 &lt;br /&gt;
00 00 80 3F 00 00 00 41 00 00 80 00 80 00 80 00 80 00 80 00 80 00 80 &lt;br /&gt;
01 01 02 00 		// color_add_blue&lt;br /&gt;
00 00 80 3F 00 00 00 00 00 00 80 00 80 00 80 00 80 00 80 00 80 00 80 &lt;br /&gt;
00 00 80 3F 00 00 00 41 00 00 80 00 80 00 80 00 80 00 80 00 80 00 80 &lt;br /&gt;
&lt;br /&gt;
// Не понимаю как, но эта триада подкрашивает уже переведенное в &lt;br /&gt;
// чб изображение, то есть делаем слегка синеватым результат, заодно&lt;br /&gt;
// огрубляем слегка красные или зеленые.&lt;br /&gt;
&lt;br /&gt;
6C 10 00 00  		// free2&lt;br /&gt;
01 01 02 00 		// color_base_red&lt;br /&gt;
CD CC CC 3D 00 00 00 00 00 00 80 00 80 00 80 00 80 00 80 00 80 00 80 &lt;br /&gt;
CD CC CC 3D 00 00 00 41 00 00 80 00 80 00 80 00 80 00 80 00 80 00 80 &lt;br /&gt;
01 01 02 00 		// color_base_green&lt;br /&gt;
CD CC CC 3D 00 00 00 00 00 00 80 00 80 00 80 00 80 00 80 00 80 00 80 &lt;br /&gt;
CD CC CC 3D 00 00 00 41 00 00 80 00 80 00 80 00 80 00 80 00 80 00 80 &lt;br /&gt;
01 01 02 00 		// color_base_blue&lt;br /&gt;
CD CC 4C 3E 00 00 00 00 00 00 80 00 80 00 80 00 80 00 80 00 80 00 80 &lt;br /&gt;
CD CC 4C 3E 00 00 00 41 00 00 80 00 80 00 80 00 80 00 80 00 80 00 80 &lt;br /&gt;
&lt;br /&gt;
// В сером режиме все красные обьекты - белым, синие и зеленые - черным&lt;br /&gt;
&lt;br /&gt;
7C 00 00 00  		// free3&lt;br /&gt;
01 01 02 00 		// color_gray_red&lt;br /&gt;
00 00 80 3F 00 00 00 00 00 00 80 00 80 00 80 00 80 00 80 00 80 00 80 &lt;br /&gt;
00 00 80 3F 00 00 00 41 00 00 80 00 80 00 80 00 80 00 80 00 80 00 80 &lt;br /&gt;
01 01 02 00 		// color_gray_green&lt;br /&gt;
00 00 80 BF 00 00 00 00 00 00 80 00 80 00 80 00 80 00 80 00 80 00 80 &lt;br /&gt;
00 00 80 BF 00 00 00 41 00 00 80 00 80 00 80 00 80 00 80 00 80 00 80 &lt;br /&gt;
01 01 02 00 		// color_gray_blue&lt;br /&gt;
00 00 80 BF 00 00 00 00 00 00 80 00 80 00 80 00 80 00 80 00 80 00 80 &lt;br /&gt;
00 00 80 BF 00 00 00 41 00 00 80 00 80 00 80 00 80 00 80 00 80 00 80 &lt;br /&gt;
&lt;br /&gt;
// Полностью черно-белое изображение с учетом правил color_gray_*&lt;br /&gt;
01 01 02 00 		// gray&lt;br /&gt;
00 00 80 3F 00 00 00 00 00 00 80 00 80 00 80 00 80 00 80 00 80 00 80 &lt;br /&gt;
00 00 80 3F 00 00 00 41 00 00 80 00 80 00 80 00 80 00 80 00 80 00 80 &lt;br /&gt;
&lt;br /&gt;
01 01 00 00 		// blur&lt;br /&gt;
&lt;br /&gt;
// Двоения в глазах не будет&lt;br /&gt;
&lt;br /&gt;
01 01 00 00 		// duality_h&lt;br /&gt;
01 01 00 00 		// duality_v&lt;br /&gt;
&lt;br /&gt;
// Шума не будет&lt;br /&gt;
01 01 00 00 		// noise_intensivity&lt;br /&gt;
01 01 00 00 		// noise_granularity&lt;br /&gt;
01 01 00 00			// noise_fps&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Ссылки===&lt;br /&gt;
Утилиты так или иначе связанные с этим форматом:&lt;br /&gt;
*[http://stalkerin.gameru.net/modules.php?name=Downloads&amp;amp;d_op=getit&amp;amp;lid=331 xrFSL src 18/06/08] от '''Neo]['''&lt;br /&gt;
*[http://stalkerin.gameru.net/modules.php?name=Downloads&amp;amp;d_op=getit&amp;amp;lid=352 Ppe Editor 1.2.0] от '''SmanxX1'''&lt;br /&gt;
[[Категория:Форматы_файлов]]&lt;/div&gt;</summary>
		<author><name>94.141.39.153</name></author>	</entry>

	<entry>
		<id>http://stalkerin.gameru.net/wiki/index.php?title=Space_restrictor</id>
		<title>Space restrictor</title>
		<link rel="alternate" type="text/html" href="http://stalkerin.gameru.net/wiki/index.php?title=Space_restrictor"/>
				<updated>2010-02-22T09:04:49Z</updated>
		
		<summary type="html">&lt;p&gt;94.141.39.153: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Начало==&lt;br /&gt;
----------------------------------------------------------&lt;br /&gt;
Значит распаковываем алл.спавн с помощью ACDC...Распаковали.&lt;br /&gt;
Откроем,например,alife_l02_garbage.ltx.&lt;br /&gt;
в самом конце допишем:&lt;br /&gt;
&lt;br /&gt;
[2145]&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;; cse_abstract properties&amp;lt;/nowiki&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
section_name = space_restrictor&amp;lt;br /&amp;gt;&lt;br /&gt;
name = sgm_kvest&amp;lt;br /&amp;gt;&lt;br /&gt;
position = 41.297409057617,0.44233170151711,-299.86953735352&amp;lt;br /&amp;gt;&lt;br /&gt;
direction = 0,0,0&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;; cse_alife_object properties&amp;lt;/nowiki&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
game_vertex_id = 253&amp;lt;br /&amp;gt;&lt;br /&gt;
distance = 0&amp;lt;br /&amp;gt;&lt;br /&gt;
level_vertex_id = 214760&amp;lt;br /&amp;gt;&lt;br /&gt;
object_flags = 0xffffff3e&amp;lt;br /&amp;gt;&lt;br /&gt;
custom_data = &amp;lt;&amp;lt;END&amp;lt;br /&amp;gt;&lt;br /&gt;
[logic]&amp;lt;br /&amp;gt;&lt;br /&gt;
active = sr_idle&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
[sr_idle]&amp;lt;br /&amp;gt;&lt;br /&gt;
on_actor_inside = %+story_sgm_kvest2_3%&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
END&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;; cse_shape properties&amp;lt;/nowiki&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
shapes = shape0&amp;lt;br /&amp;gt;&lt;br /&gt;
shape0:type = box&amp;lt;br /&amp;gt;&lt;br /&gt;
shape0:axis_x = 6.5,0,0&amp;lt;br /&amp;gt;&lt;br /&gt;
shape0:axis_y = 0,6.5,0&amp;lt;br /&amp;gt;&lt;br /&gt;
shape0:axis_z = 0,0,6.5&amp;lt;br /&amp;gt;&lt;br /&gt;
shape0:offset = 0,0,0&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;; cse_alife_space_restrictor properties&amp;lt;/nowiki&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
restrictor_type = 3&amp;lt;br /&amp;gt;&lt;br /&gt;
----------------------------------------------------------&lt;br /&gt;
где: &amp;lt;br /&amp;gt;&lt;br /&gt;
[2145] - порядковый номер;&amp;lt;br /&amp;gt;&lt;br /&gt;
section_name = space_restrictor - имя секции(HаM надо space_restrictor);&amp;lt;br /&amp;gt;&lt;br /&gt;
name = svalka_prikol - имя(задаём любое);&amp;lt;br /&amp;gt;&lt;br /&gt;
position = - позиции(место где будем спавнить его);&amp;lt;br /&amp;gt;&lt;br /&gt;
direction = - поворот рестриктра(не трогаем..);&amp;lt;br /&amp;gt;&lt;br /&gt;
game_vertex_id = гейм вертекс;&amp;lt;br /&amp;gt;&lt;br /&gt;
level_vertex_id = - левел вертекс;&amp;lt;br /&amp;gt;&lt;br /&gt;
----------------------------------------------------------&lt;br /&gt;
==Координаты==&lt;br /&gt;
Примечание:&amp;lt;br /&amp;gt;&lt;br /&gt;
координаты спавна, game_vertex_id и level_vertex_id можно получить с помощью функции:&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
function main_menu:OnButton_credits_clicked() &amp;lt;br /&amp;gt;&lt;br /&gt;
local text &amp;lt;br /&amp;gt;&lt;br /&gt;
local vid &amp;lt;br /&amp;gt;&lt;br /&gt;
local gvid &amp;lt;br /&amp;gt;&lt;br /&gt;
local a = vector() &amp;lt;br /&amp;gt;&lt;br /&gt;
local text &amp;lt;br /&amp;gt;&lt;br /&gt;
a = db.actor:position() &amp;lt;br /&amp;gt;&lt;br /&gt;
vid = db.actor:level_vertex_id() &amp;lt;br /&amp;gt;&lt;br /&gt;
gvid = db.actor:game_vertex_id() &lt;br /&gt;
text = &amp;quot;Позиция:\\nX= &amp;quot;..a.x..&amp;quot;\\nY= &amp;quot;..a.y..&amp;quot;\\nZ= &amp;quot;..a.z..&amp;quot;\\nlevel_vertex= &amp;quot;..vid..&amp;quot;\\ngame_vertex_id= &amp;quot;..gvid &amp;lt;br /&amp;gt;&lt;br /&gt;
news_manager.send_tip(db.actor, text, nil, nil, 30000) &amp;lt;br /&amp;gt;&lt;br /&gt;
end&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
просто допишите её в ui_main_menu.script,в самом конце.&amp;lt;br /&amp;gt;&lt;br /&gt;
----------------------------------------------------------&amp;lt;br /&amp;gt;&lt;br /&gt;
object_flags = не трогаем (оставим 0xffffff3e)&amp;lt;br /&amp;gt;&lt;br /&gt;
custom_data = не трогаем (тоесть оставляем &amp;lt;&amp;lt;END )&amp;lt;br /&amp;gt;&lt;br /&gt;
----------------------------------------------------------&amp;lt;br /&amp;gt;&lt;br /&gt;
==Logic==&lt;br /&gt;
===Выдача infoportions===&lt;br /&gt;
теперь логика для рестриктра:&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
[logic]&amp;lt;br /&amp;gt;&lt;br /&gt;
active = sr_idle&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
[sr_idle]&lt;br /&gt;
on_actor_inside = %+имя инфопоршня%&amp;lt;br /&amp;gt;&lt;br /&gt;
END&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
С такой логикой рестриктор будет выдавать ГГ инфопоршень.&amp;lt;br /&amp;gt;&lt;br /&gt;
----------------------------------------------------------&lt;br /&gt;
===Эффекты выброса===&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
[logic]&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
active = sr_idle&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
[sr_idle]&amp;lt;br /&amp;gt;&lt;br /&gt;
on_timer = 100000| %=start_small_reject% sr_idle2&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
[sr_idle2]&amp;lt;br /&amp;gt;&lt;br /&gt;
on_timer = 100000| %=start_small_reject% sr_idle&amp;lt;br /&amp;gt;&lt;br /&gt;
END&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
такая логика будет запускать каждые 100 сек,эффекты выброса.&amp;lt;br /&amp;gt;&lt;br /&gt;
----------------------------------------------------------&lt;br /&gt;
===Проверка на наличие и выдача Infoportion===&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
[logic]&amp;lt;br /&amp;gt;&lt;br /&gt;
active = sr_idle&amp;lt;br /&amp;gt;&lt;br /&gt;
[sr_idle]&amp;lt;br /&amp;gt;&lt;br /&gt;
on_actor_inside = {=имя_инфопоршня_3 +имя_инфопоршня_2} nil %+имя_инфопоршня_1%&amp;lt;br /&amp;gt;&lt;br /&gt;
END&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
{=имя_инфопоршня_3 +имя_инфопоршня_2} - это проверка(условие) что у ГГ есть нужный инфопоршень.Если есть,то рестриктор выдаст нужный инфопоршень.&amp;lt;br /&amp;gt;&lt;br /&gt;
----------------------------------------------------------&amp;lt;br /&amp;gt;&lt;br /&gt;
==Shapes==&lt;br /&gt;
Двигаем дальше.&amp;lt;br /&amp;gt;&lt;br /&gt;
shapes = тут вписываем названия шейпов&amp;lt;br /&amp;gt;&lt;br /&gt;
Пример:&amp;lt;br /&amp;gt;&lt;br /&gt;
shapes = shape0&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
shape0:type = - это тип шейпа.Ставить или box,или sphere.&amp;lt;br /&amp;gt;&lt;br /&gt;
box - коробка&amp;lt;br /&amp;gt;&lt;br /&gt;
sphere - сфера&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
shape0:axis_x = ваша цифра,0,0&amp;lt;br /&amp;gt;&lt;br /&gt;
shape0:axis_y = 0,ваша цифра,0&amp;lt;br /&amp;gt;&lt;br /&gt;
shape0:axis_z = 0,0,ваша цифра&amp;lt;br /&amp;gt;&lt;br /&gt;
- размеры шейпа.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
restrictor_type - тип рестриктра.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
я везде ставлю restrictor_type = 3,поэтому сказать не могу на что влияет значение.&amp;lt;br /&amp;gt;&lt;br /&gt;
Ну вот и всё.Думаю всё чётко и ясно.Будут вопросы обращайтесь.&amp;lt;br /&amp;gt;&lt;br /&gt;
ПС: спасибо р-09 за объяснение некоторых моментов с логикой.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
space restrictor&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Статью написал джЭдай,SGMTeam.&amp;lt;br /&amp;gt;&lt;br /&gt;
Статью преобразовывал в вики (неправильный перенос строк, ошибки с отсутствием некоторых знаков, запись в категорию) - '''Rekongstor'''&lt;br /&gt;
&lt;br /&gt;
[[Категория:Скрипты]]&lt;/div&gt;</summary>
		<author><name>94.141.39.153</name></author>	</entry>

	<entry>
		<id>http://stalkerin.gameru.net/wiki/index.php?title=3dsmax_2010._%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_%D1%82%D0%B5%D1%80%D1%80%D0%B5%D0%B9%D0%BD%D0%B0</id>
		<title>3dsmax 2010. Создание террейна</title>
		<link rel="alternate" type="text/html" href="http://stalkerin.gameru.net/wiki/index.php?title=3dsmax_2010._%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_%D1%82%D0%B5%D1%80%D1%80%D0%B5%D0%B9%D0%BD%D0%B0"/>
				<updated>2010-02-22T09:03:22Z</updated>
		
		<summary type="html">&lt;p&gt;94.141.39.153: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Инструменты. ==&lt;br /&gt;
В работе использован плагин экспорта в формат[http://www.stalkerin.gameru.net/downloads/SDK/xraymaxtools-20090821.rar .object]&lt;br /&gt;
&amp;lt;br/&amp;gt;И сам 3D’s Max 2010&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Начало работ ==&lt;br /&gt;
[[Изображение:B3fa0ddb2803.jpg|thumb|Плоскость и Панель]]&lt;br /&gt;
Открываем 3д макс, создаем, например, плоскость '''Object Type &amp;gt; Plane '''. Она должна быть небольшой, так как в процессе работы она нам не понадобится и мы её удалим.&lt;br /&gt;
&amp;lt;br /&amp;gt;А сейчас кликаем по ней правой кнопкой мыши Convert to &amp;gt; Editable Poly &amp;gt; и видим что сверху в панели управления(FreeForm) появилось две вкладки ''Poly Draw'' и ''Paint Deform''[[Изображение:Example.jpg|thumb|Тропинки]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt; Далее кликаем Poly Draw и выбираем '''Strips'''. Рисуем тропинки для нашей локации. После того, как они будут готовы, плоскость которую мы создали, нужно удалить.&lt;br /&gt;
&amp;lt;br&amp;gt; Теперь у нас есть несколько тропинок, но они не соединены между собой.&lt;br /&gt;
Переходим  в режим редактирования Edge'eй, правой кнопкои '''&amp;gt; Convert to &amp;gt; Editable Poly &amp;gt; Edge '''&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Соединяем между собой тропинки, чтобы это сделать выделяем нужный эдж, после чего кликаем по кнопке''' Bridge''' в свитке ''Edit Edges'' - Готово!&lt;br /&gt;
&lt;br /&gt;
== Создание земли ==&lt;br /&gt;
Повторяем процедуру с плоскостью, но теперь в ''Poly Draw''  выбираем не Strips а''' Shapes'''&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt; Опять рисуем, только уже не тропинки а землю. Должно получится как то так*.[[Изображение:Wwrdsad.jpg|thumb|как то так*]]&lt;br /&gt;
Теперь осталось дать материал земле и дороге. Выделяем их поочерёдно, нажимаем кнопку M(Ь) &amp;gt; Standart &amp;gt; в открывшемся окне выбираем '''X-Ray Material'''.&amp;lt;hr&amp;gt;&amp;lt;br&amp;gt;Напротив texture кликаем по None&amp;gt; Bitmap &amp;gt; Находим текстуру для объекта.&amp;lt;br&amp;gt;Напротив параметров: &amp;lt;br&amp;gt;''Engine/Compiler Shader'' и ''Game Material'' выбираем из списка нужные вам!&lt;br /&gt;
&amp;lt;br&amp;gt; Растягиваем текстуру по обьекту с помошью '''Unwrap UVW''' (Сonvert to Editable Poly &amp;gt; Modifier List &amp;gt; Unwrap UVW ) &lt;br /&gt;
&amp;lt;br&amp;gt;'''Готово!'''&lt;br /&gt;
&amp;lt;br&amp;gt; Теперь осталось лишь экспортировать полученный terrain в '''Level Editor'''&lt;br /&gt;
&amp;lt;br&amp;gt; Выделяем все объекты. В левом верхнем углу кликаем по значку макса &amp;gt; '''Export &amp;gt; Export &amp;gt; Сохраняем в нужном вам мете на диске X '''(можно сразу в папке rawdata/objects или просто кинуть в папку import)&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;hr&amp;gt;Теперь осталось лишь загрузить терреин в Level Editor'e расставить спауны, лаиты и глоу, объекты и можно компилировать уровень!&lt;br /&gt;
&lt;br /&gt;
[[Категория:SDK]]&lt;/div&gt;</summary>
		<author><name>94.141.39.153</name></author>	</entry>

	<entry>
		<id>http://stalkerin.gameru.net/wiki/index.php?title=3dsmax._%D0%A0%D0%B0%D0%B1%D0%BE%D1%82%D0%B0_%D1%81_Unwrap_UVW</id>
		<title>3dsmax. Работа с Unwrap UVW</title>
		<link rel="alternate" type="text/html" href="http://stalkerin.gameru.net/wiki/index.php?title=3dsmax._%D0%A0%D0%B0%D0%B1%D0%BE%D1%82%D0%B0_%D1%81_Unwrap_UVW"/>
				<updated>2010-02-22T09:00:02Z</updated>
		
		<summary type="html">&lt;p&gt;94.141.39.153: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Подготовка==&lt;br /&gt;
===Предисловие===&lt;br /&gt;
&lt;br /&gt;
Эта статья рассчитана на людей, не понимающих всех моментов работы в Max'е&lt;br /&gt;
&lt;br /&gt;
Некоторые вообще не умеют накладывать текстуру на модель, многие не умеют применять текстуру к определённой части объекта, но всё же очень многие не умеют пользоваться Unwrap UVW. О нём уже упоминалось в [[Создание_моделей_и_их_добавление_в_игру|статье по созданию 3d моделек]]&lt;br /&gt;
&lt;br /&gt;
Но тем не менее она была не подробной. Например научился накладывать текстуру я только в одном из уроков из ЛКИ :D&lt;br /&gt;
Поэтому начнём.&lt;br /&gt;
&lt;br /&gt;
===Инструментарий===&lt;br /&gt;
* 3ds max 8&lt;br /&gt;
* Плагины экспорта (лучше будет и иметь плагины импорта тоже)&lt;br /&gt;
* X-Ray SDK&lt;br /&gt;
* Photoshop (или другой редактор... Paint.NET например)&lt;br /&gt;
* Совсем небольшие навыки создания объектов в максе (то, что не знаете, meltn описано здесь)&lt;br /&gt;
&lt;br /&gt;
==Практика==&lt;br /&gt;
===Модель===&lt;br /&gt;
Для начала я создал бокс. Потом изменил его высоту, ширину, длину:&lt;br /&gt;
 L. = 0,3&lt;br /&gt;
 W. = 0,21&lt;br /&gt;
 H. = 0,007&lt;br /&gt;
&lt;br /&gt;
Вы можете использовать свои размеры.&lt;br /&gt;
&lt;br /&gt;
[[Изображение:Rek0_UVW_-_модель.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Текстурирование===&lt;br /&gt;
====Накладываем текстуру====&lt;br /&gt;
Теперь наложите на него текстуру:&lt;br /&gt;
* Откройте Material Editor&lt;br /&gt;
 Далее я пропущу шаги, т.к. это уже не раз описывалось в уроках по теме 3ds max на Stalker Inside&lt;br /&gt;
* Вот Вы наложили текстуру (обратите внимание, что текстура должна быть одним файлом!&lt;br /&gt;
&lt;br /&gt;
[[Изображение:Rek0_UVW_-_текстура.png]]&lt;br /&gt;
&lt;br /&gt;
 Не все знают, как накладывается текстура. Поэтому напишу:&lt;br /&gt;
 - '''Зажмите''' на шарике в Material Editor левую кнопку мыши.&lt;br /&gt;
 &lt;br /&gt;
 Если передвинуть мышь, указатель станет другим (квадратная рамка и круг с крестом поверх рамки)&lt;br /&gt;
 &lt;br /&gt;
 - Перенесите текстуру на модель.&lt;br /&gt;
 &lt;br /&gt;
 Указатель снова поменяется (квадратная рамка, но только поверх неё - курсор) и появится подсказка, &lt;br /&gt;
 на какой объект мы перемещаем материал.&lt;br /&gt;
&lt;br /&gt;
 - Разожмите клавишу мыши, когда произойдёт последнее вышесказанное изменение курсора&lt;br /&gt;
&lt;br /&gt;
 Не забудьте нажать на сине-белый кубик в Mat.Editor'е (чтобы мы видели, как легла текстура)&lt;br /&gt;
&lt;br /&gt;
====Unwrap UVW====&lt;br /&gt;
Но что это? Когда мы посмотрели на модель, увидели, что текстура легла беспорядочно! Вот для этого и нужен Unwrap UVW&lt;br /&gt;
&lt;br /&gt;
Перейдите в режим Modify. Сделайте последние изменения объекта и можно создавать Un-UVW. Нажмите на свиток Modifier List\Unwrap UVW&lt;br /&gt;
&lt;br /&gt;
* Нажмите на &amp;quot;+&amp;quot; перед Unwrap UVW и выберите в открывшемся свике Face.&lt;br /&gt;
* Нажмите на нужную сторону объекта.&lt;br /&gt;
&lt;br /&gt;
[[Изображение:Rek0_UVW_-_face.png]]&lt;br /&gt;
&lt;br /&gt;
*Теперь в правой панели нажмите в свитке Parameters кнопку Edit&lt;br /&gt;
*В открывшемся окне нажмите на свиток Character Pattern и выберите в контекстном меню &amp;quot;Map#1&amp;quot; (или другой, но чтобы в скобках было написано название вашей текстуры)&lt;br /&gt;
&lt;br /&gt;
Есть 4 варианта изменения наложения и режим Mirror - для отражения текстуры по горизонатли)&lt;br /&gt;
*Move - Двигать выделенные точки&lt;br /&gt;
*Rotate - Вращать их&lt;br /&gt;
*Scale - Изменять размер&lt;br /&gt;
*Freeform mode - Поговорим отдельно.&lt;br /&gt;
&lt;br /&gt;
 FF Mode:&lt;br /&gt;
 Можно свободно изменять размер и т.д. без одновременного изменения нужного по другим осям.&lt;br /&gt;
 Чтобы изменить:&lt;br /&gt;
 Размер - Выделите точки и двигайте углы&lt;br /&gt;
 Позицию - Двигайте красную сетку&lt;br /&gt;
 Угол поворота (Rotate) - Двигайте бока выделенных точек.&lt;br /&gt;
&lt;br /&gt;
Вот мы и закончили изменение одного лица (face), затем другого...&lt;br /&gt;
&lt;br /&gt;
Потом нажмите правой кнопкой на объект и перейдите в: Convert To\Editable Mesh&lt;br /&gt;
&lt;br /&gt;
Затем в панели Modify можно отсоединять Faces и уже по-отдельности (если не получилось в одном объекте) можно создавать для объектов Un-UVW&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
И вот у меня получилась такая модель:&lt;br /&gt;
&lt;br /&gt;
[[Изображение:Rek0_UVW_-_end.png]]&lt;br /&gt;
&lt;br /&gt;
 Хм... Где-то я её уже видел.... Что-то похожее..... А! Точно!&lt;br /&gt;
 Сама игромания писала однажды урок :)). По созданию объектов в максе.&lt;br /&gt;
&lt;br /&gt;
Вот [http://www.igromania.ru/upload/articles/109/54894/models_import_04.jpg|Вот я её вспомнил] :)&lt;br /&gt;
==Заключение==&lt;br /&gt;
Мы научились накладывать на объекты текстуры, которые будут правильно ложиться в последующих действиях.&lt;br /&gt;
 Кстати.. Перед тем, как создавать Physique (или, если будете делать статический, то перед экспортом), &lt;br /&gt;
 сконвертируйте объект в Editable Mesh ещё раз на всякий...&lt;br /&gt;
&lt;br /&gt;
'''''Журнал, текстуру которого я пирменл для этой статьи - пробил мне дорогу в модмейкерство Сталкера. Без него не было бы меня здесь...'''''&lt;br /&gt;
&lt;br /&gt;
==Авторы==&lt;br /&gt;
* [[Участник:Rekongstor]] - Написал статью, проверил, показал.&lt;br /&gt;
* Stalker2012 - Подал идею &amp;lt;десу&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория:SDK]]&lt;/div&gt;</summary>
		<author><name>94.141.39.153</name></author>	</entry>

	</feed>