Четверг, 23.11.2017, 10:18

logo

Пользовательский поиск

Меню сайта
Категории раздела
Разное [15]
Tutorials
Создание карт [13]
Создание моделей [2]
Кодинг [14]
Создание карт CS [197]
Учебник cs-mapper
Свойства entity HL-CS [117]
Форма входа
Логин:
Пароль:
Наш сервер CS 1.6
Поиск
Наш опрос
Ваш телефон
Всего ответов: 102
Атмосфера
Друзья сайта


Главная » Статьи » HL Development » Создание карт CS

Учебник по созданию карт CS HL. Все об R_SPEEDS



CS-MAPPER — Создание карт для
 CS. 
 
 
Ссылки 
Статьи

Учебник по созданию карт
Глава VI. Оптимизация карты (r_speeds).

§ 6.1 Все об R_SPEEDS

Из данного материала вы узнаете об очень важном параметре R_SPEEDS, который показывает на сколько быстро отрисовывается ваш уровень. Мы расскажем, как посмотреть R_SPEEDS на созданном вами уровне и как его уменьшить в случае, если уровень тормозит.

Содержание статьи:

1. Что такое R_SPEEDS?

R_SPEEDS — это спец. параметр, который показывает число полигонов, видимых игроком в уровне. Чем больше полигонов отрисовывается, тем меньше FPS (число кадров в секунду). Если полигонов слишком много, то уровень начинает, как говорится, «тормозить».

R_SPEEDS параметр динамичный, он изменяется в зависимости от положения игрока в уровне и от направления его взгляда. В самом деле, если игрок будет смотреть в стену или в угол, то число кадров в секунду скорее всего будет максимальным 99-100. Если же игрок выйдет на открытое пространство, то FPS уменьшится, а R_SPEEDS увеличится.


2. Как узнать R_SPEEDS на своей карте?

Что же, как же нам посмотреть R_SPEEDS на своём уровне?

Проверьте, что в ярлыке для запуска Counter-Strike у вас есть параметр -console, который позволит нам открыть консоль в игре. То есть строчка запуска CS выглядит примерно так: C:\Games\HL\hl.exe -game cstrike -console.

Сделаем сервер на своём уровне. После запуска уровня, выдвинем консоль (клавиша «~») и напишем:

developer 1
r_speeds 1

После данных действий в левом углу экрана и в консоли побегут циферки (смотрите картинку ниже), которые будут меняться при перемещении игрока по уровню или при изменении направления взгляда.

Так выглядит параметр R_SPEEDS в игре

Как видно, цифры разбиты на четыре колонки. Нас интересуют колонки со словами wpoly и epoly (это две правые колонки).

310 wpoly — (от англ. world polygons) число полигонов, которые создают браши: земля, стены, крыши, скалы и пр. Это главный показатель R_SPEEDS. Чем больше wpoly, тем больше тормозит уровень.

988 epoly — (от англ. entity polygons) число полигонов, которые создают модели (руки с оружием, игроки, другие модели). Когда Вы видите на экране четыре-пять других игроков, то epoly заметно выше, нежели если вы видите одного игрока.

На 2-ух рисунках ниже наглядно видна зависимость R_SPEEDS (и FPS) от размера видимого пространства.

Этот скриншот сделан на базе террористов на карте de_aztec. Здесь R_SPEEDS равен 167 видимым полигонам (в данном направлении взгляда). Число кадров в секунду максимально и составляет 99 FPS.

Высокий FPS на базе террористов на карте de_aztec

Теперь переместимся ближе к точке закладки бомбы (у воды). Здесь R_SPEEDS гораздо выше и равняется порядка 800-850 wpoly, что вызывает уменьшение FPS до 50, как видно из картинки. Компьютер, на котором проводился тест: Pentium III 600 MHz + GeForce 256.

Низкий FPS на точке закладки бомбы на карте de_aztec

3. Каким должен быть максимальный R_SPEEDS?

Споров на тему, каким должен быть максимальный R_SPEEDS, много. Одни говорят, что параметр wpoly не должен быть выше 650 полигонов, другие допускают 1000 wpoly, приводя в качестве аргумента тот, факт, что компьютеры на данный момент довольно мощные.

Мы придерживаемся следующего мнения:

1) В местах стычек команд, там, где постоянно происходят перестрелки, количество wpoly должно быть минимально — до 650 (в идеале: 400-450).

2) На базах команд, в тех местах, где игроки появляются редко или встречаются 1 на 1, а не 5 на 5, число wpoly может быть больше — до 750-800.

После компиляции уровня, нужно побегать по всем ее местам и посмотреть R_SPEEDS. Если Вы заметите высокие значения wpoly (больше 750), то это место уровня нужно оптимизировать (читайте об этом ниже) или полностью переделать.

Ещё один совет, побегайте по стандартным Counter-Strike уровням с включённым R_SPEEDS. Вы увидите, что число wpoly на них довольно небольшое, что позволяет комфортно играть даже на маломощных компьютерах.

Epoly не такой важный показатель как wpoly, однако слишком высокие значения (больше 4000-5000 epoly) данного параметра также вызывают существенное понижение FPS (числа кадров в секунду). В принципе, на показатель epoly внимания обращать не следует. При изготовлении уровня нужно учитывать лишь значения wpoly (world polygons).


4. Причины большого R_SPEEDS

Что же, мы уже знаем, что число кадров в секунду зависит от числа видимых полигонов, которое в своем максимуме должно равняться 600-750 wpoly. А теперь посмотрим от чего же зависит число полигонов и вообще из чего получаются полигоны.

4.1 Разбиение на полигоны при соприкосновении брашей

Игровой движок HL устроен таким образом, что при соприкосновении малого браша с более крупным (к примеру, ящик стоит на земле) происходит разбиение земли на более мелкие полигоны. Посмотрим, как это происходит (белые полосы обозначают границы полигонов).

Ящик разбивает поверхность земли на более мелкие полигоны

Из картинки видно, что ящик, стоящий на полу, разбивает его своими нижними гранями на полигоны.

На следующей картинке ящик превращен в энтити-объект func_wall, а энтити-объекты НЕ РАЗБИВАЮТ браши на полигоны. Отсюда и первый способ оптимизации карты — мелкие объекты вроде ящиков можно превращать в func_wall (func_breakable, func_pushable и т.п.). Это первое важное правило, которое нужно запомнить.

Ящик, превращенный в func_wall, НЕ разбивает поверхность земли на полигоны

Совершенно неважно какой энтити-объект Вы используете (func_wall, func_breakable и т.д.) — при соприкосновении с брашами разбиения не происходит! Таким образом сберегаются полигоны.

Еще один пример: светильник, сделанный из нескольких брашей, разбивает стену.

Светильник разбивает стену на полигоны

Но если мы превратим светильник в func_illusionary, разбиения уже не будет.

Светильник, превращенный в func_illusionary, НЕ разбивает стену на полигоны

Кстати сказать, часто в узких местах в уровнях (корридоры, туннели) мелкие объекты (светильники, полки картины и т.д.) превращают func_illusionary. Это помогает, во-первых, сберечь несколько полигонов, а, во-вторых, не мешает игроку передвигаться (игрок может легко проходить сквозь func_illusionary).

Из всего этого, конечно же, не следует, что должно все ящики в уровне превращать в func_wall. В большенстве случаев мапперы оставляют их брашами. Но бывают моменты, когда просто нужно превратить тот или иной браш в энтити-объект. Вот один из таких примеров.

Предположим, в уровне вы создали отличные колонны с подставками (смотрите картинку ниже). Каждая колонна состоит из 16 боковых сторон.

Слева колонна сделана из брашей - происходит разбиение подставки на полигоны; справа подставки превращены в func_wall - разбиения нет

Слева и колонна, и подставки оставлены как обычные браши. В этом случае, обе подставки (и нижняя, и верхняя) разбиваются каждая на 16 полигонов (по числу боковых сторон колонны). Из чего следует, что на данном участке уровня число полигонов увеличивается на 32. А если мы создадим десять эдаких колонн? Полигонов будет уже 320!

Справа обе подставки были превращены в func_wall, саму же колонну мы оставили как браш. Никакого разбиения не происходит. Мы сэкономили 32 полигона!

Из картинки видно, что для отображения границ полигонов мы запустили Counter-Strike в режиме OpenGL и ввели команду gl_wireframe 1 (также можно использовать gl_wireframe 2, при этом объекты станут полупрозрачными и отобразятся все рисуемые движком полигоны).

Другой полезной консольной командой является r_drawflat 1, которую можно использовать только в режиме Software. В данном случае всякий отдельный полигон окрашивается в свой цвет.

Вот как в этом режиме будет выглядеть левая брашевая колонна:

Левая колонна, разбивающая подставку на полигоны. Режим Software и консольная команда r_drawflat 1

Вторая же колонна с подставками из func_wall выглядит так:

Правая колонна НЕ разбивает подставку на полигоны. Режим Software и консольная команда r_drawflat 1

Нужно заметить, что в обоих случаях, чтобы можно было использовать указанные консольные команды, уровень должно запускать из консоли (то есть запускаем Counter-Strike, заходим в консоль и пишем map имя_карты). Если создать сервер, как обычно, из меню, то команды работать не будут, так как они запрещены в мультиплеере.

ВАЖНО: никогда не превращайте в энтити-объекты стены (или землю!), которые составляют основу вашего уровня карты. Дело в том, что игровой движок Half-Life видит сквозь энтити-объекты и рисует все, что расположено за ними! К примеру, если за какой-то стенкой расположено полуровня и вы превратите её, например, в func_wall, то в данном будут большие тормоза из-за высокого R_SPEEDS.


4.2 Разбиение на полигоны текстурами

Как известно, текстуры имеют определенный размер, к примеру, 128 х 128 пикселей. Предположим, что у нас в уровне есть стена с размерами, большими, чем размер данной текстуры, к примеру, 256 х 256 юнитов. В данном случае хоть браш у нас и 1, но полигонов будет несколько.

К примеру, если стена имеет размеры 256 х 256, а текстура 128 х 128, то данный браш будет разбит на четыре полигона, так как площадь текстуры ровно в четыре раза меньше площади браша.

В редакторе Хаммер есть возможность менять масштаб (Scale) текстуры. Делается это на панели «Face Properties» в параметре Scale.

Здесь меняется масштаб текстур

Взгляните на рисунок ниже, на ней видно, на сколько различается число полигонов при использовании различных масштабов текстур.

На стене слева текстуры нанесены с масштабом 4х1 (полигонов всего 6), а справа — 1х1 (полигонов в 16 раз больше!)

На стене слева текстуры нанесены с масштабом 4х1 (полигонов всего 6), а справа — 1х1 (полигонов в 16 раз больше!). Конечно, левая стена выглядит более размазано, но в случае, когда нужно сократить число полигонов, данный метод может быть успешно применен. Наилучших результатов вы сможете добиться при увеличении масштаба текстур на вот таких больших по площади брашах (полу, горах).


4.3 Большие открытые пространства

Ну, и последней причиной высокого R_SPEEDS является открытость карты и избыточная насыщеность деталями.

Игровой движок HL не расчитан на большие открытые пространства (необязательно, что это открытая область с небом. Большой ангар с массой деталей тоже будет тормозить). Помните под какую игру вы создаете уровни, это не Unreal :-) Half-Life любит закрытые помещения, всякого рода коридорчики и ему очень не нравятся, высоченные горы или 40 многоэтажных зданий на одной улице. Если, созданный вами уровень тормозит, и R_SPEEDS приближается к нескольким тысячам wpoly — необходимо координальным образом изменять уровень.


5. Методы снижения R_SPEEDS

Несколько главных способов снижения R_SPEEDS мы только что разобрали в пункте четыре. Существуют и другие хитрости, которых помогут снизить R_SPEEDS на вашем уровне.

  • Превращение мелких брашей в брашевые энтити-объекты (рассмотрено)
  • Увеличение масштаба текстур (рассмотрено)
  • Закрытие обзора игрокам
  • Способ зазора в один юнит
  • Способ с использованием текстур 240 х 240 пикселей
  • Применение SKY-текстур
  • «Разделение» карты на отдельные пространства
  • Использование HINT-брашей
Рассмотрим все оставшиеся пункты кроме последнего восьмого (метод 8, как наиболее сложный — тема отдельной статьи).

5.1 Закрытие обзора игрокам

Собственно, это даже не способ как таковой. Просто уровень нужно строить таким образом, чтобы не было огромных открытых пространств.

Что понимать под большими открытыми пространствами?

Приведём реальные примеры.

Примеры больших открытых пространств на de_cbble

Примеры больших открытых пространств на de_dust2 и de_train

Примеры больших открытых пространств на de_inferno и de_aztec

Приведённые выше примеры показывают, каких максимальных размеров должны быть открытые области в Counter-Strike. Учтите ещё то, что авторы данных уровней — профессионалы, которые наилучшим образом оптимизировали свои карты.

Что же, создавая открытую область, не выходите за рамки разумного. Все дороги к данному «загруженному» месту должны быть или чем-то отгорожены (как на de_cbble огромными толстыми воротами, рис.1), или просто они должны быть изогнутыми (смотрите рисунок 2).

Отгораживаем два открытых пространства воротами

Делаем изогнутый подход вместо прямого

В обоих рассмотренных выше случаях обзор игроку закрывается, он видит меньше полигонов, следовательно FPS в данном месте будет выше.


5.2 Метод зазора в 1 юнит

Это часто встречающийся способ, суть которого заключается в поднятии браша на один юнит (можно и больше) над поверхностью земли.

В самом деле, если подумать, то в данном случае ящик, висящий над землей на расстоянии всего в один юнит, не касается ее поверхности. А если нет соприкосновения, то нет и разбиения земли на полигоны. К тому же обычный игрок (не создатель карт :-) не заметит, что ящик висит над полом, ведь он подвешен совсем на немного. Естественно, в таком случае ящик не нужно превращать в энтити-объект.

Этот способ широко применяется на таких картах как: de_train, de_nuke, de_aztec, cs_backalley. Вот, к примеру, рисунок с de_train:

Столбик и подставка на карте de_train

На рисунке видно, что бетонная подставка под столб больше его по площади. Это означает, что при соприкосновении, она была бы разбита на четыре полигона. Автор уровня сделал крохотный зазор между столбом и подставкой (1-2 юнита). Теперь соприкосновения нет, и вместо 4 полигонов мы имеем всего 2 («днище» столба и верх подставки). А если мы закрасим дно столба текстурой SKY, которая не создает полигонов (всё равно дно столба в игре никто не видит), то будет отрисован всего 1 полигон — верх подставки (об использовании SKY-текстур для оптимизации карты читайте ниже в данном материале).

Промежуток в 1 юнит между столбом и подставкой

Также на данном уровне подняты над землей все вагоны и некоторые ящики — это позволило избежать многочисленных разбиений земли.

На de_aztec не доведены до потолка провода и лампы. Между ними и потолком также есть зазор в несколько юнитов.

Промежуток в несколько юнитов между проводами с лампой и потолком на de_aztec

На de_nuke также применен данный метод (смотрите картинку ниже).

Ящик "парит" над землей

Конечно же, не стоит впадать в крайности и подвешивать абсолютно все ящики и другие объекты. Делайте это в случае надобности, при высоком R_SPEEDS.


5.3 Метод с использованием текстур 240 х 240 пикселей

Это эффективный (очень эффективный :-) способ скоращения числа полигонов. Суть заключается в том, что движок HL разбивает совершенно все поверхности через каждые 240 пикселей текстуры! Неважно, что Вы подогнали по стороне ящика текстуру 256 х 256 пикселей, она все равно будет разбита через 240 пикселей.

Сейчас мы вновь воспользуемся загрузкой уровня из консоли и драгоценной командой gl_wireframe 1 (для режима OpenGL). На рисунке ниже изображен ящик размером 256 х 256 юнитов с наложенной на него текстурой также с размерами 256 х 256, но пикселей. Применив консольную команду gl_wireframe 1, мы с удивлением откроем, что вместо одного полигона (ведь текстура всего лишь одна) у нас отрисовано целых четыре! В чем же дело? Почему на каждой стороне ящика по четыре полигона? Ведь теперь выходит, что 1 единственный ящик генерирует аж: 4 х 5 = 20 полигонов (5 — число видимых сторон)!

Так компиляторы разбивают на полигоны ящик 256 х 256 юнитов, с наложенной на него текстурой 256 х 256 пикселей

Как нам уже известно, движок HL разбивает все поверхности на полигоны через каждые 240 пикселей текстуры. Чтобы было понятнее, приведем еще одну картинку. На ней мы видим тот же ящик, но чуть поменьше — 240 х 240 юнитов. Текстура наложена в масштабе 1 к 1. Здесь мы как бы не видим часть текстуры (от нас скрыты 16 пикселей по ширине и 16 по высоте, ведь всего текстура 256 х 256 пикселей).

А теперь компиляторы не разбивают на полигоны ящик 240х240 юнитов, с наложенной на него текстурой 256х256 (текстура на 16 юнитов больше, чем сторона ящика)

И дело именно в текстурных пикселях, а не размере ящика в юнитах. Давайте посмотрим на еще один пример. Здесь ящик уже совсем небольшой 96 х 96 юнитов, а текстура все таже 256 х 256 пикселей. В редакторе мы применили к текстуре «Fit» (кнопка на панели «Face Properties»), которая вписала нашу большую текстуру до меньших размеров ящика.

Компиляторы разбивают на полигоны ящик 96х96 юнитов, с наложенной на него текстурой 256х256

Как видите, даже такая небольшая поверхность ящика разбита на четыре полигона. То есть происходит как бы отсчёт 240 пикселей на текстуре и делается «разрез». Значит, если у ящика есть 5 видимых сторон (дно мы не видим), то вместо ожидаемых пяти полигонов мы имеем двадцать! А если у нас есть десять ящиков, выходит, вместо 50 полигонов у нас будет 200! То же самое касается всех брашей, на которые наложена текстура 256 х 256 пикселей (вообще это сейчас очень популярный размер текстуры, а зря!). Часто создатели карт накладывают 256 х 256 текстуры на стены, крыши, проходы, скалы — всё это НАМНОГО увеличивает число полигонов.

Выходы здесь следующие:

  • использовать текстуры с размером 240 х 240 пикселей (лучше всего)
  • не делать «Fit» для текстур 256 х 256 (то есть чтобы видно было лишь 240 пикселей текстуры)
  • создавать стены высотой в 240 юнитов, в таком случае часть текстуры 256 х 256 будет скрыта
  • использовать параметр -subdivide х для компилятора HLBSP (вместе с ZHLT Custom Build 1.7 и выше)
Что касается последнего пункта, то команда -subdivide х (где х — значение от 240 до 512) задаёт после какого числа пикселей нужно разбивать поверхность на полигоны. НО!!! Данный параметр глючит и не дает докомпилировать уровень! :-( Во всяком случае так было с улучшенными компиляторами Зонера Custom Build 1.7. Будем верить, что в будущем эту ошибку исправят, и мы сможем использовать текстуры вплость до 512 пикселей, и при этом не будет происходить разбиения на меньшие полигоны.


5.4 Применение SKY-текстур

Как мы уже знаем, SKY-текстуры применяются для создания неба вокруг карты. Но они наделены ещё 1-им очень полезным свойством: стороны брашей или брашевых энтити, окрашенные текстурой SKY, не создают полигонов! То есть, если мы раскрасим какие-либо объекты SKY-текстурой, то они не создадут полигонов, правда, при этом будут совершенно прозрачными (через них будет видно небо :-).

SKY-текстуры необходимо наносить на те поверхности, которые в игре человек не видит: крыши домов, верхние грани заборов и стен, дно карты и т.п.

В самом деле, ведь не может же игрок увидеть крыши домов, к примеру, здесь (смотрите картинку ниже).

Обычно, игрок не видит верхние плоскости крыш (заборов, скал, стен)

В данном случае мы просто берём и раскрашиваем все крыши специальной текстурой SKY (смотрите картинку ниже).

Закрашиваем невидимые игроку поверхности текстурой SKY

Теперь на нашем уровне полигонов будет меньше + меньше времени потребуется на компиляцию, так как SKY-поверхности не нуждаются в просчёте освещённости (они просто-напросто игнорируются).

Все мы замечали, играя например на de_dust, что, если в режиме спектатора подняться чуть выше стен, то потолки становятся прозрачными (смотрите картинку ниже).

Прозрачные потолки на de_dust

Это как раз и является доказательством того, что на них была нанесена SKY-текстура с целью сокращения числа полигонов.

Важно! Если вы создаете небо большой коробкой вокруг уровня, то следует закрасить SKY-текстурой все внешние стороны карты, а также ее дно (смотрите картинку ниже).

При создании неба-коробки все внешние стены и дно карты необходимо закрасить SKY-текстурой

При создании неба-коробки все внешние стены и дно карты необходимо закрасить SKY-текстурой

В данном случае мы резко сокращаем время компиляции карты, так как тепрь дно карты и внешние стены не будут просчитываться на освещение.


5.5 Разделение карты на отдельные области

Теперь давайте рассмотрим последний способ (в данном материале) — метод разделения уровня на отдельные области.

Вообще этот способ по сути является способом создания «правильного» неба, когда SKY-браши создаются по периметру карты, повторяя все её внутренние и наружные стены.

Рассмотрим принцип построения карты на примере популярной de_dust2.

Вид сверху на карту de_dust2

De_Dust2 схематично можно разбить на 5 основных областей (пространств). Каждую область отделена от соседней или воротами, или проходом в стене.

Разделение на области карты de_dust2

Находясь в 1-ой из этих областей, игрок видит лишь её одну, ну, и незначительную часть соседней области (остальные пространства уровня движок HL не отрисовывает). Всё это позволяет добиться низкого R_SPEEDS и высокой скорости отрисовки уровня.

Пришло время познакомиться с ещё 1-ой полезной для тестирования уровня консольной командой: r_draworder 1.

Эта команда работает только в режиме Software и при условии, что уровень вы запускаете из консоли, а не через меню.

При использовании данной команды мы видим, как работает движок Half-Life, какие пространства уровня он отрисовывает.

Вот, к примеру, как будет выглядеть de_dust2 в 1-ой своей области.

Используем команду r_draworder 1 на карте de_dust2

Мы находимся у базы контр-террористов (точка «А»). Движок HL помимо напрямую видимых частей уровня, отрисовывает несколько больше. Так, к примеру, мы видим базу контр-террористов (под мостом) и еще часть прохода, если идти не на базу, а налево, там, где спуск и тупик. Всё остальное движок отбрасывает.

Или вот изображение третьей области (тоже около базы контр-террористов, но только у центрального прохода).

Используем команду r_draworder 1 на карте de_dust2

Здесь виден весь центральный проход (несмотря на ворота) и часть точки «В». Всё остальное также отбрасывается.


Вывод из всего этого таков: уровень нужно разбивать на пространства. Пространства должны соединяться какими-то проходами или находиться на разных высотах (одна область ниже другой).

Но бывают случаи, когда движок Half-Life, не смотря на наличие перед взором игрока высокой стены, все же отрисовывает области, находящиеся за данной стеной. К примеру, в таком случае:

Из-за малой высоты стенки игровой движок "видит", что находится за ней

Игрок, обозначенный фиолетовым параллелепипедом, в действительности не видит, что расположено за стеной, однако игровой движок рисует это пространство уровня. Происходит это, по всей видимости, из-за недостаточной высоты стены.

Однако, иногда и действительно высокие стены не помогают. К примеру, движок может «заглядывать» за стенку высотой в 320-400 юнитов. Что же тут поделать?

Это можно исправить созданием над стеной SKY-браша. Данный SKY-браш повторяет форму стены и занимает по высоте всю область от её верхней части до неба (верхнего SKY-браша).

А теперь не видит :)

В другом примере с воротами (смотрите картинку ниже) данный прием вряд ли поможет сократить число видимых полигонов, так как движок прекрасно видит сквозь отверстие ворот. Но, если игрок напрямую не будет видеть ворота (посмотрит в сторону), то этот приём также может сработать, и игровой движок Half-Life отрежет часть карты за воротами.

Та же ситуация, но с воротами. Рис.1

А посему и в данном случае советуем создать SKY-браш между воротами и верхним SKY-брашем.

Та же ситуация, но с воротами. Рис.2

Так нужно поступить со всей картой — разделить ее SKY-брашами на отдельные пространства. Кстати, при создании общего освещения можно сделать всего один объект light_environment, поместить его в любое из пространств, и все пространства будут нормально освещены, то есть делать несколько источников света (light_environment) нет надобности.

Глава VI. Оптимизация карты (r_speeds).

§ 6.1   Все об R_SPEEDS

К оглавлению Учебника

Категория: Создание карт CS | Добавил: SuperStart (02.03.2012)
Просмотров: 741 | Теги: Half-Life, counter-strike 1.6, Counter-Strike, counter strike, Halflife | Рейтинг: 0.0/0 |


Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]

Copyright www.akksimo.net © 2017