Перейти к контенту

Курилка программистов


Рекомендуемые сообщения

@Viнt@rь, о производительности приложения надо думать, когда оно либо написано, и можно заняться полезной оптимизацией (переписать запросы к БД например), либо уже тормозит на столько, что код пишется со скоростью выполнения программы.

это потеря в скорости выполнения программы

Это потеря потерь. (с) :D

ТЧ 1.0004. SAP и Trans mod

github

Ссылка на комментарий

@Viнt@rь, ну я как-бы вот совсем не об этом вопрошал (лично для себя вообще ничего не просил и не прошу). Устройство всех этих модулей я понимаю, и об ооп луа я осведомлен. Да и тему, на которую ты ссылаешься, прочел довольно давно. К слову, вообще много форумов прочел на первых порах (в ч. разделы по ковырянию). Мне кажется что тут одни неназываемые не оказывают должного почтения другим неназываемым (ну или хотя-бы того, но которое последние рассчитывают), вестимо, скоро их самообман раскроется, и первых отправят они за {восточные ворота}.

Ссылка на комментарий

нафиг все эти скрипты, сразу все в исходниках сделаю как хочу, соберу, и... гм. А что, собственно, и ?

Это очень плохая идея. Разделение на движок и скрипты позволяет распределить роли при разработке игры, поскольку скриптёры могут делать своё дело без влезания в дебри движка. Разумеется, это хорошо работает при наличии внятного и хорошо документированного интерфейса. Кстати, разделение на код и данные несёт туже функцию: кто-то написал код, управляемый внешними данными - конфигами, бинарными данными и т.п. Потом код не трогаем, а меняем только данные. Поэтому кстати плохо задавать данные прямо в коде, поскольку их изменение - это изменение кода.

 

Даже при использовании fastcall-а "пролетало"? %)

Да. фастколл на самом деле в последних патчах игры в точности совпадает по частоте вызовов с апдейтом актора.

 

game_time() - проблема с разрядностью. Да, так называемое "45-е мая". Ну, тут все по разному решают. Я вот, опять же, остановился на том, что 45 игровых дней на одной локации без единой перезагрузки сидеть вряд-ли кто будет.

Это решается только одним способом, использованием класса CTime, который даёт полный доступ к движковому 64-х разрядному счётчику. Других способов нет. Сидит игрок на локации 45 дней или нет - роли не играет, поскольку в игре полно глобальных объектов, которые обновляются и на других локациях: респавнеры те же, да и вообще все процессы, связанные со временем - выброс, таймеры и т.п.

 

ООП в Lua - не ООП вовсе,

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

 

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

Я мог бы с этим согласиться, если бы не поставленный акцент. ООП - это не просто какое-то там удобство. Реальные проблемы при создании крупных программных систем - это не производительность программы, а производительность программистов, которая радикально падает при усложнении создаваемой системы. Падает вплоть до нулевого или даже отрицательного значения (т.е. при определённых условиях деятельность разработчиков становится попросту деструктивной). Поэтому все современные подходы к разработке так или иначе имеют дело с контролем сложности разрабатываемой системы. ООП - это как раз фундаментальный подход к контролю сложности системы. Да, сам по себе ООП не даёт никаких алгоритмических преимуществ. Не становится ОО программа ни быстрее, ни меньше. Но она становится проще, причём надо понимать, что накладные расходы при использовании ООП имеются не только в скорости работы и расходе памяти, но и чисто в тексте кода. Появляются некие дополнительные синтаксические элементы, их надо понимать, они занимают некое дополнительное место, ОО компоненты требуют несколько больших усилий при своём создании, требуются расходы на проектирование системы классов и т.д. Эти расходы выглядят совершенно неприемлемыми при создании минимальной программы аля "Hello, World!", что даёт повод некоторым утверждать, что ООП - шлак и без него можно обойтись. Однако, при разработке мало-мальски сложной системы эти накладные расходы уже становятся существенно меньшими в относительном измерении. При этом сложность разработки снижается радикально, что и является конечной целью. Снижается за счёт инкапсуляции, скрывания реализации, упрощения повторного использования кода за счёт наследования и полиморфизма и т.д.

 

На мой взгляд работа над глобальным модом - более чем весомая причина для контроля сложности и значит широкого внедрения парадигмы ООП. К слову сказать, вся игра в целом, движок да и скриптовые интерфейсы, все сделаны в парадигме ООП. Очень хороший пример такого подхода. Там есть определённые косяки, но вообще стоит поучиться.

  • Спасибо 2
  • Нравится 2
  • Согласен 4
 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Ссылка на комментарий

@Malandrinus, все мною изложенное писалось в пол третьего ночи, потому я пытался не вбиваться в подробности и по-быстрому вкратце ответить Карлану на вот это:

Ну и я, как дилетант, прошу показать, если не затруднит, что все-таки лучше использовать, структурное, или ооп, а не мерятся тут сами знаете чем.

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

 

ООП - это не просто какое-то там удобство

Ведь, если не лезть в дебри применения, все в том же "вкратце" это можно назвать удобством :) Ну, а если все таки лезть: для чего именно, в какие моменты, как и за счет чего... - в своем посте ты уже и так растолковал.

 

С этим не соглашусь, поскольку ООП - это не конкретный синтаксис в конкретном языке, а парадигма.

Все же я наверное сильно категорично выразился. Больше склоняюсь к кое-когда сказанному xStream - термину псевдо-ООП. Как бы наследование есть, объектная ориентированность тоже есть, а вот допустим инкапсуляции и полиморфизма нет...

Изменено пользователем Viнt@rь
Ссылка на комментарий

это можно назвать удобством

Ну наверное можно =) Развивая эту мысль можно также сказать, что неудобно пользоваться тем, чем не владеешь. Нет понимания идеи ООП - конечно и пользоваться им будет неудобно, а скорее всего и невозможно. Поэтому каждый использует те подходы, которые знает. В конечном счёте важен результат. Просто при использовании традиционных процедурно-ориентированных подходов достигаться он будет гораздо большими затратами.

инкапсуляции и полиморфизма нет

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

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Ссылка на комментарий

Всем здравия!

Столько "заскриптованного мата" мне читать не доводилось никогда. Не красиво, господа...

Мериться нужно доводами, а не мнениями. Тогда, возможно, будет польза для всех читающих и не будут подниматься вопросы об "умирании модинга". То, что прочёл выше - это его добивание...

Всем мудрости и терпения!

Изменено пользователем warwer
  • Нравится 2
Ссылка на комментарий
Просто при использовании традиционных процедурно-ориентированных подходов достигаться он будет гораздо большими затратами.

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

 

@warwer, сразу скажу не наезд, а интереса ради, ну да бы понять, я нагадил или нет. Потому не стоит ниже мною написанное воспринимать в штыки.

заскриптованного мата

вроде бы от меня не поступало такого :)

 

То, что прочёл выше - это его добивание...

имеется ввиду наше обсуждение парадигмы ООП?

 

Точно не о тебе писал. - warwer

Изменено пользователем warwer
  • Нравится 1
Ссылка на комментарий

@Viнt@rь, по себе могу сказать, что мне пришлось поработать над собой, чтобы проникнуться идеями ООП и кое-какими азами ОО дизайна. Это потребовало усилий, а помог в этом дедушка Borland Pascal ещё под DOS. Чем-то меня тогда заворожил и язык и идея ООП.

 

=) Тем более мои усилия были героическими, что начинал я программировать на диалектах Basic-а, где можно было из программы манипулировать текстом программы и переходить по номеру строки. Лепота. Как вспомню, так вздрогну.

  • Нравится 1
  • Согласен 1
 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Ссылка на комментарий
Ну как это нет?! Инкапсуляция - это объединение кода и данных. Нет скрытия реализации, поскольку нет атрибутов приватности у полей, но это не так уж критично. Полиморфизм тоже есть. Каждый метод - виртуальный, поскольку каждый объект явно содержит ссылки на функции.

а за это спасибо :) учту и говоря за инкапсуляцию я и имел ввиду скрытие реализации, а точнее ее отсутствие.

 

Сам каждый день, так сказать, вынужден использовать ООП ибо Java(Android) от этого там никуда не уйдешь. Возможно у меня возникла некая путаница в реализации принципов в Lua и в Java(C#, C++)

 

ЗЫ "вынужден" сказано не с досадой, а наоборот, так как самому нравятся идеи и применение ООП.

Изменено пользователем Viнt@rь
Ссылка на комментарий

- А что, собственно, и ?

- Это очень плохая идея. Разделение на движок и скрипты позволяет распределить роли при разработке игры,

 

Ну вот я тоже примерно про это. Собственно, при отсутствии в сталкере скриптовой части, которую оказалось возможно изменять, не факт, что вообще моды на Сталкер были бы. Ну или максимум - маргинальные проекты, как те, в которых в 201* году маленькая группка любителей все еще перепиливает игрушки под дос первой половины 90-х...

 

Кстати, здесь же мы подходим и к вопросу об ООП. Когда я писал про "не знаю, что это такое " - в общем, да, было некое утрирование. На самом деле есть места, где инкапсуляция (на самом деле изоляция) и наследование дают определенное удобство. Так же, как есть и некоторые проблемы. Вот недавно столкнулся с тем, что, действительно, game_object может существовать в нескольких экземплярах, и изменения родителю не передаются, хотя надо.

Пришлось, хе-хе, через ненавистный многим pstor.

 

И в общем-то дискутабельный вопрос о гомогенности кода: должно-ли все-все быть оформлено в едином стиле, даже если это неудобно (ну, то есть, включая printf( "Hello world" ), или в некоторых случаях процедурщина все же уместна.

 

Вот пресловутый profile_timer() показывает, что в определенных случаях процедурщина смысл таки имеет (и ожидание 6-8 сек vs. 13 - это мелочь на фоне 5 минут, но когда те 5 сведены к 0.2 - то и 13 vs. 6 - тоже заметно).

А коли так - может и hello world в обычную функцию развернуть не грех ?

 

А продолжая рассуждения общетеоретические, то васик vs. ООП - оно, конечно, да. Но вот начав работать с C, причем сразу с ленточной/дисковой подсистемой, и имея набор хорошо организованных пресловутых .h (зато без линкера ;), что, собственно, и заставляло думать о содержании этих самых .h) - некоторые более поздние находки кажутся не таким уж и достижением Мировой Мысли, а Страустрап - скорее даже и вредным.

 

 

2 Desertir: "либо уже тормозит на столько, что код пишется со скоростью выполнения программы." - приложение запускается дольше, чем пишется код. И тогда уже вот честно становится лениво натравливать на каждый кусок profile_timer(), вместо того чтобы просто взять, и банально снести 20 вызовов функций из полусотни скриптов, результатом которых - получение одного битика.

Изменено пользователем Dennis_Chikin
Ссылка на комментарий

@Dennis_Chikin, тормозами могут являться не только 20 вызовов функций в полусотне скриптов. Не во всех приложениях есть "скрипты", не везде есть "апдейты", а "приложение" это не только ценный мех Сталкер. Кстати, для профилирования существуют различные тулзы, которые нам наглядно показывают, где "узко" (dotTrace к примеру для донета). Но, если уж брать наше поле брани (то бишь скрипты), то я видел две обертки для профайлера, но вслепую весьма трудно найти, какие же участки кода действительно съедают много времени, либо смотреть на поведение игры, либо засекать каждую функцию, либо уповать на свой профессионализм и быть уверенным, что вот такая-то функция будет тормозить. А можно еще глобальный профайлер сделать, который будет собирать статистику со всех скриптов.

 

И еще одно кстати, про время приложения в целом. Игрок ждет по сути два раза, первое - когда же выйдет игра, и второе - когда она загрузится и будет игратцо, время на приобретение не в нашей власти (торрент или покупка в магазине). Я иногда "воображаю" такую формулу: общее_время = время_разработки + время_вычислений * кол-во_пользователей. И я могу жертвовать либо временем разработки, тогда, скорее всего, пострадает время вычислений - пользователь получит свое приложение скажем через месяц, но еще будет ждать час, пока оно заведется + тормоза при самом использовании. Либо наоборот, жрем много времени на разработку, пользователь получит быстрое приложение, но только через пол года. В чем суть - я бы не рассматривал только время вычислений, а старался бы найти некий баланс.

  • Согласен 1
  • Полезно 1

ТЧ 1.0004. SAP и Trans mod

github

Ссылка на комментарий

Ага, когда имеем софт для управления рэйдом, или даже для банальной записи CD - иногда приходится задумываться о том, что может его в следующую major версию, или пусть пользователи себе все болванки позапорют, а кому повезет - просто перестанет оборудование работать после апдейта. Или пусть просто пока подождут обновляться/покупать железо новых моделей. ;)

Да, возвращаясь к ООП, тут наверное стоит скорее подумать о таком факторе, как стоимость управления разработкой. Ну, то есть, и во времени, и в деньгах, и в собственно людях.
Сколько-то десятков лет жили без ООП, и даже без dll ;) и ничего. И 640Kb - это было действительно очень много, по тому как работало и в 16-ти.
Но, требовалась довольно таки серьезная дисциплина. Примерно оттуда - "один файл целиком на экране", системы наименований файлов, наименований функций, что куда должно передаваться и т.д.
И вообще - один модуль, который на входе получает текст и на выходе выдает текст.
Потом, да, еще придумали линкеры и возможность собирать .obj в .lib

Да, с ООП ни о чем таком думать не надо - "не хочешь - заставим". Хотя в принципе, при соблюдении драконовской дисциплины скорость разработки не страдает ни разу. Скорее даже, наоборот, отсутствуют лишние телодвижения.

2 Viнt@rь: "драконовская" - это про меры по оформлению модулей и их взаимодействия.

 

upd: ну, да, опять неправильное слово использовал. Скорее что "сопровождение" да. Драконовость в случае процедурщины  - она подразумевает, что раз написанная функция всегда будет принимать те аргументы, которые принимала, именно в том виде, всегда возвращать результат тоже в заданном однажды виде, и лежать на своем месте. Сама написана так, что открыв файл - сразу понятно, что она делает. На глобальные переменные опять же пишутся спеки, и сам выбор имен заранее оговаривается. И т.д.

В случае с ООП ко всему этому можно относиться гораздо проще.

Изменено пользователем Dennis_Chikin
Ссылка на комментарий
Хотя в принципе, при соблюдении драконовской дисциплины скорость разработки не страдает ни разу. Скорее даже, наоборот, отсутствуют лишние телодвижения.

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

 

2 Viнt@rь: "драконовская" - это про меры по оформлению модулей и их взаимодействия.

Уточнять же нужно сразу :) у каждого своя практика, потому и свои взгляды на одни и те же вещи.

 

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

Изменено пользователем Viнt@rь
Ссылка на комментарий

 

 

Больше склоняюсь к кое-когда сказанному xStream - термину псевдо-ООП.

Ненене, девидблейн :) Я это говорила не про луа. А про простую реализацию, которую я выкладывала. Она была очень упрощенной, потому и была "всевдо-ооп" - я хотела показать, что не так уж и сложно реализовать парадигму с помощью ЛУА.

  • Полезно 1

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Ссылка на комментарий

 

 

при соблюдении драконовской дисциплины скорость разработки не страдает ни разу. Скорее даже, наоборот, отсутствуют лишние телодвижения. ... "драконовская" - это про меры по оформлению модулей и их взаимодействия.

Увы, мой собственный опыт говорит об обратном. Самодисциплина нужна вообще всегда, используем мы ООП или нет, но при использовании процедурно-ориентированного подхода в большом проекте мы создаём код, более чувствительный к ошибкам. Дисциплина или нет, а ошибки мы делаем всегда. Среди причин такой бо'льшей чувствительности навскидку можно назвать:
1. Слабое управление областями видимости, засорение глобальной области. Отсюда конфликты имён, трудности с поиском нужных данных.
2. Удалённость кода и данных. Это одна из причин, по которой мне так и не удалось избавиться от таймеров АМК. Вызываются они в одном месте, а их проверка и срабатывание - совершенно в другом. Поэтому тяжело понять по таймеру, где он реально используется.
3. Затруднение повторного использования кода, что приводит к копипасте и дублированию кода. При дальнейшем изменении возникают несогласованности.

Здесь речь больше не о написании, а о сопровождении кода. Стоимость сопровождения процедурного кода многократно больше, чем спроектированного в ОО стиле. Однако, вопреки расхожему мнению, сопровождать свой код программист начинает сразу после написания. Хороший код никогда не пишется раз и навсегда. Написав что-то, я же буду переписывать это снова и снова неделю, месяц спустя. Кто-то другой будет этим кодом пользоваться, и трудность понимания замедлит уже его действия. ООП здесь реально помогает.

В качестве лирического отступления. Именно для упрощения сопровождения я очень густо комментирую свой код. Почти буквально каждую строку. Я делаю это не для кого-то, а для себя. Здорово упрощает жизнь неделю спустя, когда смотришь на свою функцию, как баран на новые ворота, и думаешь: "Это я что-ли написал? А это вообще что?"
  • Согласен 5
  • Полезно 1
 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Ссылка на комментарий

 

 

Именно для упрощения сопровождения я очень густо комментирую свой код.

Тоже в качестве лирики: у нас принято писать self-explaining код. Если появились комментарии, значит где-то код перестал быть тривиальным, и это тревожный звоночек.

Это не значит, что их не должно быть: если логика нетривиальна или громоздка и это не исправить (а иногда просто незачем), они необходимы.

  • Согласен 1

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Ссылка на комментарий

у нас принято писать self-explaining код

self explained код - это миф. Что можно сделать, чтобы код говорил сам за себя, кроме того, что красиво его отформатировать и дать переменными и функциям внятные имена? Я это в обязательном порядке делаю, но этого совершенно недостаточно.

Мои комментарии внутри кода я мог бы разделить на несколько типов. Первый - декларация намерений. Как правило, это короткие фразы, которые объясняют, что именно в целом делает последующий фрагмент кода и зачем. Например

-- ищем ближайшего бандита

Второй тип - декларация состояния. Я поясняю себе, в каком состоянии находится (должна находиться) моя программа в этой точке. Что я ожидаю в такой-то переменной и т.д. Переменная то может и иметь говорящее название, но её значение может быть не определено, и она может быть не одна. Кроме того, я выделяю так подмножество важных именно в данный момент данных Например (после какого-то вызова):

-- имеем в массиве xxx список таких-то объектов yyy или код ошибки в zzz

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

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

for id=0,65535 do -- среди всех объектов на уровне
    local cobj = level.object_by_id(id)
    if cobj and cobj:is_stalker() and is_bandit(npc) then -- ищем сталкеров-бандитов
        if distance_between(db.actor, cobj) < 20.0 then -- в пределах 20 метров от актора
            -- и что-то ужасное с ними делаем
        end
    end
end

Соберите все эти комментарии во фразу и вы получите: "найти бандитов в радиусе 20 метров от актора и оторвать им бошки". Это в сущности декларация о намерениях, просто более подробная и размазанная уже по фрагменту кода. Я здесь конечно утрировал, поскольку вероятно не буду комментировать именно такой фрагмент, но идею надеюсь изложил. Хочу сказать, что подобные комментарии я часто пишу перед написанием собственно кода. Они мне помогают.

 

Совсем забыл добавить о разных хаках и трюках. В модостроении, особенно под сталкер, без этого никак. Комментарии в этом случае строго обязательны: что, зачем, почему, какую проблему хотим обойти.

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

 

ЗЫ: Вероятно, пысы тоже думали что-то такое насчёт self explained кода, и потому не комментировали вообще, т.е. совсем никак. Насколько я могу понять, это вызвало у второго поколения разрабов лютую радость. Это когда первый состав свалил, а новые люди стали допиливать рендер и т.п. Мы все помним, чем это закончилось.

Изменено пользователем malandrinus
  • Нравится 1
  • Согласен 1
 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Ссылка на комментарий

self explained код - это миф.

Не миф. Это идеал, к которому надо стремиться. Не бывает 100% самокоментируемого кода, как не бывает 100% безглючного кода или 100% ооп кода. Но к ним можно стремиться :)

 

К примеру твой кусок кода вполне самокомментируемый:

for id=0,65535 do
    local cobj = level.object_by_id(id)
    if cobj and cobj:is_stalker() and is_bandit(npc) then
        if distance_between(db.actor, cobj) < 20.0 then
            remove_head(cobj)
        end
    end
end
А вот наличие комментариев только усложняет его модификацию. Увеличил радиус поиска бандитов - надо править в двух местах: в коде и в комментарии :)

 

Хорошо было бы конечно забацать итератор по онлайновым объектам... Тогда было бы вообще, как в комментариях:

for _, cobj in pairs(level.objects) do
    if is_bandit(cobj) and distance_between(db.actor, cobj) < 20.0 then
            remove_head(cobj)
        end
    end
end
  • Согласен 1
  • Полезно 1
Ссылка на комментарий

@abramcumner

Но в итоге всё равно делаем то же самое.

Поэтому первой строкой перед кодом не помешает поставить коммент

 

"-- найти бандитов в радиусе 20 метров от актора и оторвать им бошки"

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

 

А вообще - уже веселее. Код фигня. Главное коммент )) Шучу ессестно. Ну, как минимум, пытаюсь )

Изменено пользователем Nazgool
Ссылка на комментарий

Всегда пишите комменты к коду, гы-гы-гы.

А никто не видел какие нибудь луавские модули для реализации аля LINQ. Ну всякие аггрегаторы, итераторы, иногда забавно.

level.objects:where(function(cobj)
    return is_bandit(cobj) and distance_between(db.actor, cobj) < 20.0
end):foreach(function(cobj) remove_head(cobj) end)

ТЧ 1.0004. SAP и Trans mod

github

Ссылка на комментарий

Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий

Комментарии могут оставлять только зарегистрированные пользователи

Создать аккаунт

Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!

Зарегистрировать новый аккаунт

Войти

Есть аккаунт? Войти.

Войти
  • Недавно просматривали   0 пользователей

    • Ни один зарегистрированный пользователь не просматривает эту страницу.
×
×
  • Создать...