Prostomod 1 311 Опубликовано 17 сентября (изменено) Спойлер Когда изучаешь более-менее серьёзный движок, обязательно к нему найдёшь документацию, в которой будут расписаны все классы и функции, доступные для использования, а так-же зачем они нужны. И как всем известно, у X-Ray ничего такого нет помимо lua_help.script (и тот не всегда вносит ясность, учитывая что создатели кастомных движков часто игнорируют его). Вот и мне, создавая очередной скрипт, пришла идея создать некий аналог документации по скриптовому API движка, то есть о том, что вынесено в скрипты. А так как разрабатываю мод на Advanced X-Ray, то и списочек буду делать для него. Однако, несмотря для это, его можно будет применить и для оригинального ЗП, для чего я буду помечать, является ли что-то не оригинальным, и при необходимости откуда. Так что если возле функции нет любой пометки, значить её с 99.9% можно использовать и в оригинальном ЗП. Как все могут догадаться, написать полную документацию даже по оригинальному движку требует титанических усилий, и я сомневаюсь, что получится это всё сделать. Поэтому я надеюсь, что другие модмейкеры (особенно те, кто разрабатывает на AXR) тоже захотят написать документацию и решатся мне помочь. Также хочу напомнить, что делаться это всё будет добровольно и безвозмездно, поэтому возможен довольно большой перерыв (или вообще забрасывание идеи) между частями документации. Чем более полезным окажется эта идея, тем больше шансов, что я буду это активно развивать. Спойлер Предполагается, что документация будет распределена по блокам, основанных на функциях script_register из движка. Решено так сделать для простоты мониторинга, написана ли для определённых скриптов документация или нет. Предполагается, что если какая-то из функций расписана, значит и остальные функции из той же функции script_register класса расписана. Каждая функция написана в формате: (*если присутствует, где добавлено) <типы выходных значений или void> имя функции(параметры и их тип). Если записи со звёздочкой нет, значит она есть в оригинальном ЗП. После этого идёт список входных и выходных параметров в том же порядке, что и их порядок в самой функции. Поля "Вход" или "Выход" могут быть упущены если для них нету параметров. Последним пунктом идёт краткое описание этой фунции, для чего она вообще нужна. Каждый блок будет спрятан под спойлер, также как и методы и поля класса и поля перечислений. Для поиска документации для конкретной функции лучше всего пользоваться поиском по теме. Пример того, как оформлять документацию будет указан ниже в шапке в виде документации по классу .ltx конфигов. Остальное будет добавляться в виде постов в теме с добавлением ссылки в шапку. Также будут добавляться ссылки и на посты других пользователей в случае, если они придерживаются формату документации. Также разрешено простое обсуждение (но при этом просьба не использовать тему как аналог вопросницы, задавая тут вопросы по моддингу). Если в документации замечен знак вопроса, то это значит, что написавшему это до конца (либо совсем) не понятно, что это такое. В таком случае других, кто знает ответ на вопрос, могут подсказать. Если получен ответ, большая просьба поправить свой пост, заменив знак вопроса на информацию. Некоторые из типов в функциях и переменных: u8 - числа от 0 до 255 u16 - числа от 0 до 65535 u32 - числа от 0 до 2^32-1 u64 - числа от 0 до 2^64-1 s8 - числа от -128 до 127 s16 - числа от −32 768 до 32 767 s32 - числа от -2^31 до 2^31-1 s64 - числа от -2^63 до 2^63-1 float - числа с плавающей запятой string - строки bool - булевые значения (те что принимают или true, или false) function - передача функции как переменной кастомный тип класса, зарегистрированного в lua Спойлер Спойлер bool section_exist(string S) Вход: имя секции Выход: есть секция или нет Проверка на наличие секции в конфигах bool line_exist(string S, string L) Вход: имя секции; имя ключа Выход: есть ключ в секции или нет Проверка на наличие определённого ключа в секции Int r_clsid(string S, string L) Вход: имя секции; имя ключа Выход: скриптовый class id в виде числа Получить скриптовый class id из значения по ключу bool r_bool(string S, string L) Вход: имя секции; имя ключа Выход: булевое значение Получить булевое значение ключа Int r_token(string S, string L, const CScriptTokenList &token_list) Вход: имя секции; имя ключа; ? Выход: массив токенов и его размер? ? string r_string_wq(string S, string L) Вход: имя секции; имя ключа Выход: строка Получить строку? u32 line_count (string S) Вход: имя секции Выход: число Получить количество ключей в секции string r_string (string S, string L) Вход: имя секции; имя ключа Выход: строка Получить строковое значение u32 r_u32 (string S, string L) Вход: имя секции; имя ключа Выход: число Получить число по ключу (беззнаковое целочисленное) s32 r_s32 (string S, string L) Вход: имя секции; имя ключа Выход: число Получить число по ключу (знаковое целочисленное) float r_float (string S, string L) Вход: имя секции; имя ключа Выход: число Получить число по ключу (число с плавающей точкой) Fvector r_vector (string S, string L) Вход: имя секции; имя ключа Выход: вектор Получить значение векторного типа [bool, string, string] r_line (string S, int L) Вход: имя секции; номер строки в секции Выход: существование ключа; имя ключа; значение ключа в виде строки Получить значение в строке под номером (CoC) void w_bool(string S, string L, bool V, string comment) Вход: имя секции; имя ключа; булевое значение; комментарий Добавить в секцию ключ с булевым значением и комментарием (CoC) void w_color(string S, string L, u32 V, string comment) Вход: имя секции; имя ключа; целочисленное беззнаковое значение; комментарий Добавить в секцию ключ с целочисленным беззнаковым значением и комментарием (CoC) void w_fcolor(string S, string L, Fcolor V, string comment) Вход: имя секции; имя ключа; значение типа Fcolor; комментарий Добавить в секцию ключ со значением типа Fcolor и комментарием (CoC) void w_float(string S, string L, float V, string comment) Вход: имя секции; имя ключа; значение в виде числа с плавающей запятой; комментарий Добавить в секцию ключ со значением в виде числа с плавающей запятой и комментарием (CoC) void w_fvector2(string S, string L, Fvector2 V, string comment) Вход: имя секции; имя ключа; значение типа Fvector2; комментарий Добавить в секцию ключ со значением типа Fvector2 и комментарием (CoC) void w_fvector3(string S, string L, Fvector3 V, string comment) Вход: имя секции; имя ключа; значение типа Fvector3; комментарий Добавить в секцию ключ со значением типа Fvector3 и комментарием (CoC) void w_fvector4(string S, string L, Fvector4 V, string comment) Вход: имя секции; имя ключа; значение типа Fvector4; комментарий Добавить в секцию ключ со значением типа Fvector4 и комментарием (CoC) void w_s16(string S, string L, s16 V, string comment) Вход: имя секции; имя ключа; значение типа s16; комментарий Добавить в секцию ключ со значением типа s16 и комментарием (CoC) void w_s32(string S, string L, s32 V, string comment) Вход: имя секции; имя ключа; значение типа s32; комментарий Добавить в секцию ключ со значением типа s32 и комментарием (CoC) void w_s64(string S, string L, s64 V, string comment) Вход: имя секции; имя ключа; значение типа s64; комментарий Добавить в секцию ключ со значением типа s64 и комментарием (CoC) void w_s8(string S, string L, s8 V, string comment) Вход: имя секции; имя ключа; значение типа s8; комментарий Добавить в секцию ключ со значением типа s8 и комментарием (CoC) void w_string(string S, string L, string V, string comment) Вход: имя секции; имя ключа; строковое значение; комментарий Добавить в секцию ключ со строковым значением и комментарием (CoC) void w_u16(string S, string L, u16 V, string comment) Вход: имя секции; имя ключа; значение типа u16; комментарий Добавить в секцию ключ со значением типа u16 и комментарием (CoC) void w_u32(string S, string L, u32 V, string comment) Вход: имя секции; имя ключа; значение типа u32; комментарий Добавить в секцию ключ со значением типа u32 и комментарием (CoC) void w_u64(string S, string L, u64 V, string comment) Вход: имя секции; имя ключа; значение типа u64; комментарий Добавить в секцию ключ со значением типа u64 и комментарием (CoC) void w_u8(string S, string L, u8 V, string comment) Вход: имя секции; имя ключа; значение типа u8; комментарий Добавить в секцию ключ со значением типа u8 и комментарием (CoC) void save_at_end(bool b) Вход: значение флага Записывать значение в конец секции? (CoC) void remove_line(string S, string L) Вход: имя секции; имя ключа Удалить ключ в секции (CoC) void set_override_names(bool b) Вход: значение флага Установить флаг ? (CoC) u32 section_count() Выход: количество секций Получить количество секций (CoC) void section_for_each(function functor) Вход: функция для вызова Пройтись по всем секциям и вызвать функцию для каждой из них. Функция должна принимать аргумент типа string, в который будет передаваться имя текущей секции. (CoC) void set_readonly(bool b) Вход: значение флага Выставить флаг, является ли файл только для чтения (CoC) string fname() Выход: имя .ltx файла Получить имя файла конфига CScriptIniFile* system_ini() Выход: конфиг настроек Получить конфиг настроек CScriptIniFile* game_ini() Выход: конфиги игры Получить конфиги игры CScriptIniFile* create_ini_file (string ini_string) Вход: имя файла Выход: файл конфига Создать файл конфига с определённым именем Спойлер Изменено 2 октября пользователем Prostomod Добавил информацию 10 1 2 Мод в разработке - X-7: Эпицентр Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Cyrax 422 Опубликовано 17 сентября Лично мне это нафиг не нужно, но ты делаешь точно очень полезное дело! Главное, что бы хватило сил довести всё до ума. Сил тебе, Простомод! И надеюсь коллеги по цеху не бросят тебя одного! 1 Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Supremeee 497 Опубликовано 18 сентября Я поплачу о том, что тут нет пояснения что за код и что он делает 1 Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Paracetamol 900 Опубликовано 18 сентября 4 часа назад, Supremeee сказал: Я поплачу о том, что тут нет пояснения что за код и что он делает Это для прогеров 1 Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Prostomod 1 311 Опубликовано 18 сентября (изменено) Спойлер Спойлер Класс объекта, хранящего информацию о конкретном цвете float r Переменная, хранящее значение R-канала цвета (красный) Диапазон от 0.0 до 1.0 Доступно чтение и запись float g Переменная, хранящее значение G-канала цвета (зелёный) Диапазон от 0.0 до 1.0 Доступно чтение и запись float b Переменная, хранящее значение B-канала цвета (синий) Диапазон от 0.0 до 1.0 Доступно чтение и запись float a Переменная, хранящее значение A-канала цвета (альфа канал) Диапазон от 0.0 до 1.0 Доступно чтение и запись Доступно создание объекта в lua, аргументов не требует void set(float r, float g, float b, float a) Вход: значение красного (диапазон от 0.0 до 1.0); значение зелёного (диапазон от 0.0 до 1.0); значение синего (диапазон от 0.0 до 1.0); значение альфы (диапазон от 0.0 до 1.0) Назначить значения в каналах (каждый канал как отдельное число) void set(Fcolor dw) Вход: объект типа Fcolor Скопировать значения каналов из другого объекта void set(u32 dw) Вход: 4-байтовое число, каждый байт представляет собой значение канала RGBA от 0 до 255 Назначить значения в каналах (передача значения через одно 32-х битное число) Спойлер Спойлер Класс флагов, вмещает 16 различных флагов Доступно создание объекта в lua, аргументов не требует u16 get() Выход: число, каждый бит которого представляет значение соответствующего флага Получить разом значения флагов в виде одного 16-битного числа flags16 zero() Выход: текущие значения флагов в объекте Выставить всем флагам значение false flags16 one() Выход: текущие значения флагов в объекте Выставить всем флагам значение true flags16 invert() Выход: текущие значения флагов в объекте Инвертировать значение всех флагов flags16 invert(flags16 other) Вход: объект типа flags16 с информацией Выход: текущие значения флагов в объекте Скопировать значения флагов из другого объекта и инвертировать их flags16 invert(u16 mask) Вход: маска флагов, которые надо инвертировать Выход: текущие значения флагов в объекте Инвертировать только те флаги, чьи значения указаны в маске. То есть для маски 4 (побитово 000000000100) будет инвертирован только 3 справа бит. flags16 assign(flags16 other) Вход: другой объект типа flags16 с флагами Выход: текущие значения флагов в объекте Назначить флагам значения такие же, как и в другом объекте flags16 assign(u16 mask) Вход: маска флагов Выход: текущие значения флагов в объекте Назначить значения флагов как в маске flags16 set(u16 mask, bool value) Вход: маска изменяемых флагов; новое значение в тех флагах Выход: текущие значеня флагов в объекте Назначить флагам из маски новое значение bool is(u16 mask) Вход: маска требуемых значений флагов Выход: соответствие текущих значений флагов маске Сравнение маски и флагов и возвращение результата bool is_any(u16 mask) Вход: маска проверяемых флагов Выход: наличие значение true в любом из проверяемых флагов Проверка определённых флагов на наличие правдивого значения у любого из них bool test(u16 mask) Полностью аналогично is_any flags16 or(u16 mask) Вход: маска, с которой надо проводить операцию Выход: текущие значения флагов Провести побитовое ИЛИ между каждым флагом и соответствующим битом в маске. flags16 or(flags16 other, u16 mask) Вход: объект типа flags16 с флагами; маска, с которой проводить операцию Выход: текущие значения флагов в объекте Провести побитовое ИЛИ между каждым флагом из другого объекта и соответствующим битом в маске, и сохранить результат в текущий объект. flags16 and(u16 mask) Вход: маска, с которой надо проводить операцию Выход: текущие значения флагов Провести побитовое И между каждым флагом и соответствующим битом в маске. flags16 and(flags16 other, u16 mask) Вход: объект типа flags16 с флагами; маска, с которой проводить операцию Выход: текущие значения флагов в объекте Провести побитовое И между каждым флагом из другого объекта и соответствующим битом в маске, и сохранить результат в текущий объект. bool equal(flags16 other) Вход: другой объект Выход: результат сравнения Сравнения значений флагов в двух объектах. Возвращает true если они все одинаковы. bool equal(flags16 other, u16 mask) Вход: другой объект; маска сравнения Выход: результат сравнения Сравнения значений флагов в двух объектах. Возвращает true если они все одинаковы. Сравнение происходит только для битов равных в маске true. Спойлер Класс флагов, вмещает 32 различных флагов Доступно создание объекта в lua, аргументов не требует u32 get() Выход: число, каждый бит которого представляет значение соответствующего флага Получить разом значения флагов в виде одного 32-битного числа flags32 zero() Выход: текущие значения флагов в объекте Выставить всем флагам значение false flags32 one() Выход: текущие значения флагов в объекте Выставить всем флагам значение true flags32 invert() Выход: текущие значения флагов в объекте Инвертировать значение всех флагов flags32 invert(flags32 other) Вход: объект типа flags32 с информацией Выход: текущие значения флагов в объекте Скопировать значения флагов из другого объекта и инвертировать их flags32 invert(u32 mask) Вход: маска флагов, которые надо инвертировать Выход: текущие значения флагов в объекте Инвертировать только те флаги, чьи значения указаны в маске. То есть для маски 4 (побитово 0000000000000000000000000100) будет инвертирован только 3 справа бит. flags32 assign(flags32 other) Вход: другой объект типа flags16 с флагами Выход: текущие значения флагов в объекте Назначить флагам значения такие же, как и в другом объекте flags32 assign(u32 mask) Вход: маска флагов Выход: текущие значения флагов в объекте Назначить значения флагов как в маске flags32 set(u32 mask, bool value) Вход: маска изменяемых флагов; новое значение в тех флагах Выход: текущие значеня флагов в объекте Назначить флагам из маски новое значение bool is(u32 mask) Вход: маска требуемых значений флагов Выход: соответствие текущих значений флагов маске Сравнение маски и флагов и возвращение результата bool is_any(u32 mask) Вход: маска проверяемых флагов Выход: наличие значение true в любом из проверяемых флагов Проверка определённых флагов на наличие правдивого значения у любого из них bool test(u32 mask) Полностью аналогично is_any flags32 or(u32 mask) Вход: маска, с которой надо проводить операцию Выход: текущие значения флагов Провести побитовое ИЛИ между каждым флагом и соответствующим битом в маске. flags32 or(flags32 other, u32 mask) Вход: объект типа flags32 с флагами; маска, с которой проводить операцию Выход: текущие значения флагов в объекте Провести побитовое ИЛИ между каждым флагом из другого объекта и соответствующим битом в маске, и сохранить результат в текущий объект. flags32 and(u32 mask) Вход: маска, с которой надо проводить операцию Выход: текущие значения флагов Провести побитовое И между каждым флагом и соответствующим битом в маске. flags32 and(flags32 other, u32 mask) Вход: объект типа flags32 с флагами; маска, с которой проводить операцию Выход: текущие значения флагов в объекте Провести побитовое И между каждым флагом из другого объекта и соответствующим битом в маске, и сохранить результат в текущий объект. bool equal(flags32 other) Вход: другой объект Выход: результат сравнения Сравнения значений флагов в двух объектах. Возвращает true если они все одинаковы. bool equal(flags32 other, u32 mask) Вход: другой объект; маска сравнения Выход: результат сравнения Сравнения значений флагов в двух объектах. Возвращает true если они все одинаковы. Сравнение происходит только для битов равных в маске true. Не знаю, насколько полезна инфа про эти 3 класса, но раз взялся всё вносить с список, значит и их обходить стороной нельзя. Изменено 18 сентября пользователем Prostomod 1 Мод в разработке - X-7: Эпицентр Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Lone_Loner 81 Опубликовано 19 сентября Что-то на высокоинтеллектуальном "Вы даже не представляете, сколько модов бы я мог разработать, если умел". Помогите с заготовкой для мода, пожалуйста. #free_SamArt Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Prostomod 1 311 Опубликовано 19 сентября Lone_Loner Да на самом деле разобраться нетрудно. Это просто будет банальный список с краткой справкой всего того, что работающие со скриптами модмейкеры могут использовать из движка. Своеобразная шпаргалка для программистов. 1 Мод в разработке - X-7: Эпицентр Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Prostomod 1 311 Опубликовано 2 октября (изменено) Давно ж я ничего не выкладывал тут. Пришло пополнение по документации, в этот раз довольно распространённые функции алайфа. Спойлер Спойлер Общий класс-менеджер системы алайф bool valid_object_id(u16 object_id) Вход: 16-битное число, ид объекта Выход: корректен ли ид Проверка ид на корректность u32 get_level_id() Выход: ид текущего уровня Получение ид текущего уровня string get_level_name(int level_id) Вход: ид уровня Выход: имя уровня Получить имя уровня по ид cse_alife_dynamic_object object(u16 object_id) Вход: ид объекта Выход: серверный объект Получить серверный объект по ид cse_alife_dynamic_object object(u16 object_id, bool no_assert) Вход: ид объекта; флаг о расширенной ошибке Выход: серверный объект Получить серверный объект по ид. При назначении флагу true выводит больше информации если объекта не найдено. cse_alife_dynamic_object story_object(u16 id) Вход: story id объекта в виде числа Выход: серверный объект Получить серверный объект по story id void set_switch_online(u16 id, bool value) Вход: ид объекта; значение флага Разрешить или запретить объекту переход в онлайн void set_switch_offline(u16 id, bool value) Вход: ид объекта; значение флага Разрешить или запретить объекту переход в оффлайн void set_interactive(u16 id, bool value) Вход: ид объекта; значение флага Активировать или деактивировать объект void kill_entity(cse_alife_monster_abstract object, u16 GraphID, cse_alife_schedulable schedulable) Вход: объект, который надо убить; вертекс глобального графа; убийца? Убить сущность, назначить ей позицию на глобальном графе и, если это аномалия, заспавнить арт? void kill_entity(cse_alife_monster_abstract monster, u16 game_vertex_id) Вход: объект, который надо убить; вертекс глобального графа Убить сущность и назначить ей позицию на глобальном графе void kill_entity(cse_alife_monster_abstract monster) Вход: объект, который надо убить Просто убить сущность void add_in_restriction(cse_alife_monster_abstract monster, u16 id) Вход: существо, которому надо добавить; ид рестриктора Добавить существу рестриктор типа IN (зона, где оно не может ходить) void add_out_restriction(cse_alife_monster_abstract monster, u16 id) Вход: существо, которому надо добавить; ид рестриктора Добавить существу рестриктор типа OUT (зона, в пределах которой существо может ходить) void remove_in_restriction(cse_alife_monster_abstract monster, u16 id) Вход: существо, у которого надо убрать рестриктор; ид рестриктора Убрать IN рестриктор у существа void remove_out_restriction(cse_alife_monster_abstract monster, u16 id) Вход: существо, у которого надо убрать рестриктор; ид рестриктора Убрать OUT рестриктор у существа void remove_all_restrictions(u16 id, ERestrictorTypes restriction_type) Вход: существо, у которого надо убрать рестрикторы; тип убираемого рестриктора Убрать все рестрикторы определённого типа у существа cse_alife_dynamic_object create(u16 spawn_id) Вход: спавн ид предмета Выход: серверный объект Заспавнить объект по спавн ид cse_abstract create(string section, Fvector position, u32 level_vertex_id, u16 game_vertex_id) Вход: секция нового объекта; позиция в онлайне объекта; вертекс АИ сетки; вертекс глобального графа Выход: новый серверный объект Заспавнить новый объект на определённой позиции в мире cse_abstract create(string section, Fvector position, u32 level_vertex_id, u16 game_vertex_id, u16 id_parent) Вход: секция нового объекта; позиция в онлайне объекта; вертекс АИ сетки; вертекс глобального графа; ид объекта, внутрь которого спавним Выход: новый серверный объект Заспавнить новый объект внутрь другого cse_abstract create_ammo(string section, Fvector position, u32 level_vertex_id, u16 game_vertex_id, u16 id_parent, int ammo_to_spawn) Вход: секция нового объекта; позиция в онлайне объекта; вертекс АИ сетки; вертекс глобального графа; ид объекта, внутрь которого спавним; количество патронов Выход: новый серверный объект пачки патронов Заспавнить пачку патронов. Если id_parent валиден, то спавним внутрь объекта, иначе на уровень void release(cse_abstract object) Вход: серверный объект на удаление Удалить объект u16 spawn_id(u32 spawn_story_id) Вход: спавн стори ид предмета Выход: спавн ид предмета Получить спавн ид предмета по спавн стори ид предмета u16 spawn_id(string obj_name) Вход: имя объекта Выход: спавн ид предмета Получить спавн ид предмета по имени cse_alife_creature_actor get_actor() Выход: серверный объект актора Получить серверный объект актора (Anomaly или OXR) void teleport_object(u16 id, u16 game_vertex_id, u32 level_vertex_id, Fvector position) Вход: ид объекта; вертекс глобального графа; вертекс АИ сетки; позиция в онлайне Телепортировать объект (Anomaly или OXR) void iterate_objects(luabind::functor<bool> functor) Вход: функция, принимающая cse_alife_dynamic_object и возвращающая true когда надо закончить итерирование. Проитерировать все серверные объекты в мире игры, вызвав функцию для каждого из них пока не найдём нужный (Anomaly или OXR) void IterateInfo(u16 id, const luabind::functor<void>& functor) Вход: ид предмета, для которого проводим итерацию инфопоршней; функция, принимающая ид объекта и инфопоршень? Проитерировать у объекта все инфопоршни, вызвав функцию для каждого из них bool has_info(u16 id, string info_id) Вход: ид объекта для проверки; инфопоршень для проверки Проверить наличие поршня у объекта bool dont_has_info(u16 id, string info_id) Вход: ид объекта для проверки; инфопоршень для проверки Проверить отсутствие поршня у объекта float switch_distance() Выход: дистанция переключения онлайн-оффлайн Получить дистанцию переключения онлайн-оффлайн (СоС) void switch_distance(float switch_distance) Вход: новая дистанция переключения онлайн-оффлайн Назначить новую дистаницю переключения онлайн-оффлайн alife_simulator alife() Выход: менеджер алайфа Получить менеджер алайфа (СоС) void set_start_position(Fvector pos) Вход: новая стартовая позиция? Назначить новую стартовую позицию? (СоС) void set_start_game_vertex_id(int id) Вход: ид стартового вертекса? Назначить новый стартовый вертекс? Кстати: если хотите, можете написать, про что в первую очередь вам бы хотелось получить документацию. Таким образом, эта тема быстрее станет по настоящему полезной. Изменено 2 октября пользователем Prostomod 1 Мод в разработке - X-7: Эпицентр Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты