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

Artos

Жители
  • Число публикаций

    1 635
  • Регистрация

  • Последнее посещение

  • Дней в топе

    7
  • AMKoin

    24 [Подарить AMKoin]

Весь контент пользователя Artos

  1. @xStream, Вот с последними словами "Если грызут и хаят предшественников, на чьем труде учились - не айс. Если грызут и говорят, что их леденец круче и вкуснее, то пусть готовятся аргументировать и доказывать." - полностью согласен. Далее предлагаю "курильщикам" не продолжать скользкие темы, принижающие одних и выпячивающие других. Труд каждого модера не заслуживает критиканства и поношений, если делается от души, а не по принуждению и/или из корысти, какова бы минимальная польза от его труда не оставалась... И хотя тут "курилка", но все же лучше говорить, ворчать и спорить по существу, а не по личностям и пристрастиям.
  2. Хм... Любить/бранить/хвалить/хаять и т.п. - конечно право каждого, но все же не должно на публичных форумах скатываться до голословного злопыхательства и подтасовок. (IMHO) @xStream, подтверди, плз, свои слова о "он натырил" конкретными фактами плагиата/воровства, или принеси извинения. 99,9% всех наработок по кодингу в СТАЛКЕРе основано на уже имеющихся наработках персвоисточника от производителей игры и последующих (мини)модах. Нужно быть глупцом, чтобы игнорировать труд других (кстати, чаще всего, выполненный именно для использования последующими кодерами!) и тужиться каждый раз изобретать велосипед. Ну а использование исходных материалов, выложенных/опубликованных в сети именно для использования в игре и создания последующих модификаций называть "натырил/своровал" - схоже с изливанием накопившейся желчи... Правильно замечено: (сорри, что не вовремя заглянул на форум)
  3. Сменил (временно) Москву на глухую провинцию... , да и хобби уже более приземленные (в буквальном смысле). Интернет тут (в моей тверской деревеньке) как в 80-ые прошлого века, но вероятно потихоньку вновь влезу в кодинг... вот только комп из Москвы нужно будет привезти, т.к. на ноуте не развернуться... А вообще... привет всем(!). Смотрю у вас тут похоже жизнь (моддинг) все еще "булькает".
  4. Artos

    Скриптование

    Да и не нужно изобретать! Первый сепаратор имеет смысл только во второй и последующих итерациях по уже усеченной строке. Ну как ты не поймешь, вроде как уже разжевал... Давай разберем такую строку, в которой заданы три состояния с синхронными звуками: state1@sound1|state2@sound2|state3@sound3 При первой итерации будет откушен кусок: state1@sound1 и останется: |state2@sound2|state3@sound3 Из откушенного будет определена 1-ая пара. Далее будет откушен: |state2@sound2 и останется: |state3@sound3 Из этого куска будет выделена 2-ая пара. Ну и напоследок из остатка будет выделена 3-я пара значений для состояния и синхронного для него звука. И все это будет упаковано в табличку и выдано функцией как результат - что и требовалось. Не требуется тут прикручивать сепаратор в начало строки. Ну а ежели прикрутишь, иль удалишь какую-нить "лишнюю" пару из строки конфига, оставив сепаратор - парсер все одно не споткнется и результат будет адекватным. , ты прав конечно, что можно и попроще все написать, но (!) все же имеем дело с наследием от оригинала и порою от многочисленных модов... А перелопачивать под новый патерн (пусть и более удобный и оптимальный) все уже имеющиеся конфиги - практически никто из геймдизайнеров/конфигеров не хочет. (тем более не так много тех, кто суть конфигов понимает). Вот и маются скриптеры с тем чтобы угодить "и нашим и вашим".
  5. Artos

    Скриптование

    @Dennis_Chikin, задавая вопрос уточняй контекст. Ранее ты спрашивал в контексте функции parse_syn_data, в которой нет state = {}. Эта строка с приравниванием относится уже к иным функциям (parse_data, ...) и далее табличка state используется для вычитывания значений в конструкциях типа r_logic.pick_section_from_condlist, и соответственно, может быть таблицей или ... Ну а почему начальный '%|*' включен в патерн (ежели имеется)? - ну так попробуй исключить и увидишь, что если вынести из патерна, то при различных заданных строках (присутствует иль нет) совершенно иной результат будет. А вот '[^|]' - не выдирается, а исключается из захвата, т.е. все до этого символа попадает в захват, а сам последующий символ остается в остатке для следующей итерации. Иными словами на вопрос "Захват первого | в подстроку - он зачем оставлен ?" можно дать такой ответ: Строка последовательными итерациями режется по символу сепаратора тогда, когда этот символ не в начале строки, а после значимого куска. Этот кусок захватывается и разбирается на составляющие его значения, а остаток строки с символом сепаратора (он уже в самом начале!) откладывается до следующей итерации, где этот начальный сепаратор и отшвыривается. И так по всем сепараторам в строке... И, в общем почти нет разницы, отбрасывать сразу или при захвате конкретных значений по второму патерну. И вообще, если хочешь понять как работают патерны - читай мануалы и проверяй на практике (есть все же отличия для find и (g)match), на форуме этим можно о-о-очень долго заниматься. В данном случае требуется из строк конфигов получать заложенные в них значения, с чем и справляются без ошибок данные функции и патерны (проверено различными искусственными тестами и используется на практике). И, конечно же(!), вариантов написания патернов может быть НЕ один - выбирай по вкусу. Важен конечный результат с учетом оптимальности по производительности. И последнее: Разработчики GSC не стали писать распарсиватели для каждого параметра в схемах логики (meet/wounded), а решили обойтись тремя боле-менее универсальными функциями/патернами. Если тебе хочется производительность поставить во главе критериев - ничего не мешает понаписать более оптимальные для каждого параметра патерны/функции. Просто будет бОльшее кол-во строк в скриптах и ... больше возможности ошибиться в применении нужной (особенно при разработке/модификации).
  6. Artos

    Скриптование

    Вообще-то не понял вопроса... т.к. в моих вариантах state - имеет строковое значение. Если ты спрашиваешь о возвращаемой таблице иль нИле - ответ ведь в самих скриптах! Смотри, например, в xr_wounded.script что распарсивается при "является ли текущий звук синхронным для текущего стейта" - ТАБЛИЦА! Т.е. если не будет таблицы - будет вылет, а пустая таблица "говорит" об отсутствии синхронизированного звука со стейтом. Хм, патерн подразумевает захват 'если таковой имеется'... и, если головою все же подумать , - в строке конфига можно задать для различных стейтов (состояний непися) различные синхронизированные звуки. Например, раненый лежит лицом к актору - просит актора аптечку, лежит спиной к актору - жалиться и стонет в пространство, ежели слегка подранен и припал на ногу - может и просто постонать... Ну, а ежели при настройках логики захотелось что-то убрать - то можно и позабыть стереть "лишний" разделитель. Вот и убивает патерн подобные "позабытости". P.S. А вот ежели не можешь использовать по какой-то причине abort'ами - не стОит уподобляться мартышке из басни дедушки Крылова, хулящей то, чего ей не потребно иль непонятно. И сама функция abort'a может быть как угодно доработана для информативности и движки бывают ра-а-азные. , в строке конфига можно задавать не только одно состояние (стэйт) требующее синхронизации со звуком... , вот и применяет разделитель (сепаратор) для каждого стейта. Точно не помню, но даже в оригинале для схемы раненого используются синхронизации на пару-тройку состояний, но это уже в индивидуальной логике смотреть нужно, а не дефолтные конфиги.
  7. Artos

    Скриптование

    Если захотелось трогать, то нужно разбираться не столь с "как работает", а "как должно работать", т.е. что же скрипт (заложенный в него алгоритм) должен выполнять с заданной ему строкою в конфиге... Функция 'parse_syn_data' в цикле должна разбивать строку по маске-символу '|' и из первой ее части (подстроки) брать данные о звуке для статуса, разбивая подстроку по маске-символу '@'. И т.о. все что после '|?' (если имеется) - откладывается для разбора в следующем подцикле итерации по строке... Вот и должен конфигер писать в конфиге для логики не абы-что, а то, что требуется и должно быть прочитано и "понято" скриптом! Т.е. чтобы начиналось не просто с "реального", а с реально значимого.
  8. И не нужно выдавать отсебятину за истину. Абсолютно бессмысленный совет/утверждение - т.к. строка из конфига логики "on_actor_inside = nil {+esc_kill_gunslinger}" полностью эквивалентна такой же "{+esc_kill_gunslinger} nil". Скрипт (xr_logic.script) разбирает эту строку, разбивая (распарсивая по маскам) на фрагменты и "от перемены мест" НИЧЕГО не изменяется, т.е. логика будет ИДЕНТИЧНА! Иначе, действия в любом слчае будут по-порядку таковыми: - проверяется наличие/отсутствие инфопоршней ( {+/-} ) и/или условий функций ( {=/!} ); - определяется (если указана) вероятность (~); - выдаются/убираются инфопоршни ( %+/-% ) и/или выполняются функции/экшены ( %...% ); - текущая секция логики сменяется следующей (или nil). Т.о. порядок указания условий-действий-секции в конфигах логики не имеет никакого значения (если, конечно, не указаны сложные составные куски, взаимовлияющие друг на друга, чего следует избегать)!
  9. @Хемуль36рус, квесты на предметы ("find_item") оперируют секцией, по которой спавнится в игру предмет. В se_item.script все секции предметов, которые могут применяться для квестов, регистрируются в таксменеджере ( task_manager.get_random_task():register_target(self) ). В самом таскменеджере задания могут выдаваться только(!) при наличии в игре соответствующих предметов (определяются по (от)регистрации секций при спавне). Т.о. если хочешь выдавать задание на предмет - позаботься чтобы предметы этого класса регистрировались при их спавне в игру по своей секции в таскменеджере. Примечание: не все классы предметов в игре имеют соответствующие Lua-классы (скрипты-конструкторы) из которых можно было бы регистрировать предметы для заданий.
  10. @Хемуль36рус, ответь, плз, на вопрос:"А что ты сам сделал чтобы понять 'почему' у тебя не выходит?" - ты отделил ошибку от алл.спавна (т.е. ошибки синтаксиса кастомдаты и схемы логики)? - ты локализовал ошибку до скрипта 'smski.script' или даже до функции 'smski.sid_sms'? - ты хотя бы можешь сказать, что твоя функция, отвечающая за выдачу СМСки вызывается логикой? ... и т.д. ... Причин великое множество, а ты предлагаешь нам гадать, а тебе "понимать"... а) Проверь, активируется ли твоя логика для твоего рестриктора (вывод нужного в лог в биндере схемы не сложно поставить); б) Проверь, вызывается ли твоя функция из логики схемы (вывод в лог из функции тоже не сложно написать); с) Если функция вызывается - проверяй аргументы и/или корректность самой функции (нам неведомой!). Судя по ее названию 'sid_sms' - в нее должен передаваться некий сид (стори_ид)... ну а если не вызывается, то, как уже упоминалось мною не раз, твой скрипт должен быть проинициализирован игрою(!), поэтому или потрудись это сделать или переноси свою функцию в xr_effects.script или arhara_dialog.script и перепроверяй.
  11. @Хемуль36рус, после твоих пояснялок можно предположить что твой вопрос (заковыка) в общем не имеет отношения к алл.спавну. - "если инфопоршень убрать игра соответственно вылетает" - это означает, что логика схемы работает или как минимум идет разбор конфига логики. Чтобы не сильно зависеть от именно алл.спавн'а можно логику (ее конфиги) вынести в отдельный файл: ustom_data = <<END [logic] cfg = scripts\my_file.ltx END и экспериментировать уже с ним, и тогда гораздо проще перепроверить вызывается ли у тебя вообще некая функция smski.sid_sms (?) и не в ней ли загвоздка... @azrael1325, чтобы "через логику вызывать скрипты из сторонних файлов" требуется доработанный скрипт 'xr_logic', и он в Народной Солянке доработан под это. Если же доработка где-то отсутствует - будет "штатный" вылет с сообщением в лог ("xr_logic: scheme '%s' is not registered in modules.script" или "object '%s': pick_section_from_condlist: function '%s' is not defined in xr_effects.script").
  12. Почему многие стали считать, что комп/приложения должны сами понимать то, что безграмотно пишет им человек? @Хемуль36рус, неужели не можешь сам проверить корректность твоей записи логики, тем более примеров в том же алл.спавне предостаточно? Уже "шапка" кастомдаты тобою исковеркана(!), а должно быть ( custom_data = <<END ... END ): custom_data = <<END [logic] active = sr_idle т.е. кастомдате объекта должно быть присвоено все, что находится между тэгами 'END'. Ну и сама строка в секции логики: [sr_idle] on_info = {+dat_hem_sms} %=smski.sid_sms% nil т.е. к 'nil' - не приравнивается что-то, а "если есть инфопоршень XXX - то выполняется функция FFF и логика сменяется на нИлевую секцию, т.е. отключается"...
  13. Из игры (скриптов) невозможно "отследить открытую вкладку(Задачи/План/Журнал...) в PDA". Вкладками(фреймами) в КПК заведует движок и ничего не вызывается и не передается скриптам. Только доработка движка (или использование внешних "приблуд") даст такую возможность. И не может сработать! Помимо синтаксической ошибки, о которой уже указано выше, в написанной (без применения головы) функции спавнится объект (local npc = alife():.. ), а далее идут попытки net-пакетами обрабатывать amk.read_stalker_params(obj) ... Т.о., в лучшем случае, если функция не вылетит по синтаксису или по отсутствующим переменным, заспавненный объект (npc->obj) после спавна просто напросто будет удален, как не нашедший работу в каком-либо гулаге.
  14. Artos

    Скриптование

    Информация в контексте вопроса о максимальном объеме net-пакета (см. #5412 и далее): (по некоторым причинам... излагать приходится несколько косноязычно... но вроде как достаточно понятно ) Имеется значение NET_PacketSizeLimit = 8192; //16384 Т.е. для ТЧ (SHoC) размер net-пакета должен быть не более 8192 байт, а для ЧН/ЗП соответственно 16384, однако(!) допустимые значения меньше объявленных/указанных. Это обусловлено тем, что для "склеивания в сэйв" - при обработке net-пакетов каждого игрового объекта для включения его данных в общий сэйв используются аналогичные функции имеющие те же ограничения и расходуются доп.байты... Эмпирическим путем определено, что расходуется порядка 512 байт (или менее). Т.о. при расчете допустимых размеров для элементов универсальных хранилищ (и вообще как ограничение для всех других объектов) следует использовать следующие значения: SHoC: NET_PacketSizeLimit = 8192 - 512 = 7680 bytes CS|CoP: NET_PacketSizeLimit = 2x8192 - 512 = 15872 bytes Примечание: Признаком переполнения net-пакета(ов) является зависание или фатальное прерывание игры на стадии записи сэйва игры. При этом лог-файл пуст(!), т.е. в лог-файле отсутствует какая-либо информация. В продвинутых способах записи в лог последней строкою будет упоминание о начале сохранений '* Saving objects':
  15. Artos

    Скриптование

    @Zander_driver, зачем же свои предполагалки мне приписывать? С самого начало было сказано: - т.е. было сказано, что этот параметр может быть добавлен к серверному объекту смарттерейна. А про нет-пакет, как и про кастом-дату, говорилось именно о 'communities'. И как раз(!), этот параметр ('accepted_communities'), отсутствующий у движкового объекта(!), объявляется из параметра 'communities', берущегося скриптом из кастомдаты объекта (т.е. может быть прочитан и нет-пакетом). Т.о. ответ на твой вопрос "как изменить" уже и был дан ранее... Примечание: Прямое изменение параметра 'obj.accepted_communities' конечно возможно, но(!) будет действовать только на текущей локации, т.е. после перезапуска игры все вернется к значению 'communities' из кастомдаты(net-пакета).
  16. Artos

    Скриптование

    @Zander_driver, и вновь очень неаккуратно излагаешь... В алл.спавне задается параметр 'communities', который относится к гулагу для этого смарттерейна и который как раз и считывается в 'accepted_communities'. В net-пакете этот параметр, как уже выше указал, нужно искать в кастомдате, и конечно же под тем же именем (communities), который и указан в алл.спавне.
  17. Artos

    Скриптование

    @Zander_driver, все же по-аккуратнее и по-понятнее стОит формулировать вопросы/посты. 1. Нет в оригинальных играх серии Сталкера объектов с сидами 'smartterrain', а есть для 'smart_terrain' (clsid.smart_terrain). Этот же сид регистрируется и в class_registrator.script. 2. Как можно сменить то, чего нет? Нет для смарт-террейнов такого понятия 'комьюнити'. Имеется возможность задать параметр 'accepted_communities' - табличку в которой перечислены допустимые/разрешенные для гулага группировки. Можно было бы net-пакетами менять в кастомдате значения для этого параметра, но... пока нет стабильных вариантов для этого класса. Но не сложно в игре в нужное время менять эту табличку (accepted_communities) по своему разумению, естественно дополнительно написав свои изменяющие функции.
  18. Artos

    Скриптование

    @Zander_driver, никто и не гонит и не требует сразу же реагировать на реплики, как и вообще писать посты без необходимой информации. Нужны логИ, по строкам которых можно было бы понять причину сбоя/ошибки. Если по какой-то причине сбой именно из-за "переполнения", то нужен лог записи, в котором были бы указаны объемы записи в каждый элемент и соответственно строки лога чтения из этих элементов из сэйва. В скрипте вывод этой информации предусмотрен. Так же, нет подозрений на превышение какой-то отдельной строки более чем 8 кБ, а есть подозрение, что или сама строка после "ручного" перевода своей таблички оказалась "странной" или еще какой-то неясный сбой при сохранении цепочки строк (пересечение имен, недопустимые символы в именах, ...) В общем не гадать нужно, а анализировать информацию (которая отсутствует)!
  19. Artos

    Скриптование

    Хотеть не вредно, но лучше их попросить... После того как посмотрел топик по разработкам в солянке, стал понятен твой интерес к этой теме. Ошибки бывают (и у тебя присутствуют) различного типа: 1. Ошибка применения необъявленной переменной: в строке else abort( "pstor_save_all, not registered type: %s, k: %s", t, k, _util.to_str( npc ) ) используется необъявленная переменная (t вместо p), что приведет к потере информации в функции прерывания игры о причине предыдущей ошибки. 2. Ошибочно предлагать "простейшую модификацию оригинала" для использования типа данных "userdata" при том, что не оговоривается обязательность наличия в таких данных неких v.classname и v:save, коих в оригинальных объектах в игре практически не встречается или имеются только в классах типа биндеров. Подобное без ограничений применения просто напросто будет вызывать ошибки при попытках модмейкеров сохранить, например, вектор позиции иль гейм-таймер (CTime) иль подобное..., а с ограничением - см.фразу о "сильно ограничивает". 3. Можно и далее продолжить разбор "простейшей модификации", но не вижу пока надобности, т.к. имеются более продвинутые варианты записи различных данных в сэйв(ы). Если есть желание сравнить и порассуждать - нет проблем, но тогда тебе придется ознакомиться с уже имеющимися вариантами (хотя бы с тем, о котором речь в исходном посте). Именно "тупо"! К твоему сведению если ты в нет-пакет что-то записал, то что-то проверять после записи уже поздно будет... т.к. если переполнение, то придется уже "выкидывать" этот нет-пакет и все перезаписывать заново. Именно на этом этапе и пишет про ошибку Zander_driver, и именно тут имеется некая неопределенность: то ли выбранная граница максимума для записи велика, то ли имеется ошибка перевода в строки и их запись в сэйв... По "преобразованию таблиц в строки" нам пока рано (иль поздно) говорить. 1. Моя позиция проста: "Любая таблица для записи в сэйв НЕ должна превышать 8 кБ! Если превышает - модмейкер должен заранее позаботиться о разделении на приемлемые части." Именно на этом основан алгоритм скрипта общего хранилища, т.е. любые строки/таблицы более 8 кБ просто игнорируются с сообщением об этом в лог. Если тебе или кому-то хочется на лету делить автоматом строки/таблицы и распределять по разным объектам с последующими слияниями - нет проблем, пишите свои варианты (с string.sub() иль иным). 2. Варианты сериализации и даже с компрессией давно уже есть и никакого чудовищного оверхеда не наблюдается. Если организовать данные и писать их в сэйв с умом(!) то даже при записи чисел строками можно выиграть в объемах! Но все конечно зависит от контента и огульно все сваливать в кучу - ошибочно! Кстати, это еще один тип ошибки (не оптимальность) в твоем варианте записи pstor'ов. Позвольте поинтересоваться: "не в скрипте" - это где? где это будет быстрее и по какой такой причине?
  20. Artos

    Скриптование

    Как можно видеть из возникших вопросов - недостаточно ясно..., а точнее для любителей шарад или гаданий.
  21. Artos

    Скриптование

    @Dennis_Chikin, ты "тихо сам с собою" иль как? Исходное сообщение Zander_driver'а о том, что при сохранении большой таблицы у него со скриптом se_stor.script возникает ошибка переполнения. Способы конвертирования таблицы в строку (иль иной тип данных) давным давно известны, применяются и в данном случае не рассматриваются (пока). Ты спросил: "Зачем переводить в строку", на что дан ответ: "Чтобы разрезать таблицу на части, т.к. строка всей таблицы превышает допустимый размер!". Ну и что же ты с чем собрался скрещивать, предлагая очередной (с ошибками и сильно ограниченный) вариант сериализации "аля xStream" при тех же самых 8-ми кило на пакет?! Автор исходного сообщения пишет об одной таблице, мною (в ответ на заданный вопрос о переводе в строки) дано пояснение (единственно возможное в данной ситуации)... Оставляю вас далее строить свои домысли и погадалки... Вот только что и кому вы пытаетесь показать иль объяснить? P.S. Вот только троллить, переходя на личности, не стОит... Теперь просто вас начну игнорировать.
  22. Artos

    Скриптование

    @Dennis_Chikin, что-то ты брякнул, что и мне сложновато понять... Во-первых, скрипт хранилища как раз и выполняет все "непосредственно в save_all/load_all". Во-вторых, полностью согласен, что в пакете актора по сути то хранить можно "копейки", но как раз в рассматриваемом случае потребно целую "кучу" где-то, но сохранять. @sapsan, тебе же уже не раз написано, что исходная таблица в данном случае содержит такое кол-во данных, что при переводе в строку (сериализации) кол-во байт строки превышает 8 кБ. А это уже не просто "удобства", а ограничение движка игры! Т.о. если хочешь использовать "удобное хранение" - потрудись не превышать размер строки в 8 кБ или же сохраняй/дроби сам как тебе вздумается. Если же все твои данные таковы, что ни при каких условиях каждая "порция" для сохранения не превысит ограничения по пакету - пользуйся сколь угодно преобразованиями.
  23. Artos

    Скриптование

    @sapsan, скрипт хранилища позволяет сохранять и табличные типы данных (и др.), но(!) если кол-во (кило)байт после перевода таблици в строку (и даже с компрессией) превысит 8 кБ - то скрипт не будет автоматом разрезать эту таблицу на куски, а ругнется в лог и пропустит эту таблицу. Т.о. если у модмейкера есть подозрения, что его таблица не влезет в один stor-элемент, то именно ему требуется озаботиться либо разбиением таблицы на несколько (что я бы рекомендовал), либо самому разбивать свою большую таблицу на нужные ему куски и их сохранять. "Удобства использования" все же имеют границы, за пределами которых начинаются неудобства. Вот тут и нужно вспоминать про оптимизацию... и выбирать критерии.
  24. Artos

    Скриптование

    @Dennis_Chikin, просто у @Zander_driver'а некорректно построенна фраза. Вероятно данные в исходной таблице имели структуру вложенных таблиц. Объем данных в таблице таков, что в сумме превышает (или может) ~8 кБ , и поэтому исходная таблица по-элементно переводилась в строки... (каждая субтаблица в свою строку), чтобы запоминать по частям.
  25. Artos

    Скриптование

    @Zander_driver, в исходном скрипте (se_stor.script) уже заложен вывод информации о кол-ве элементов хранения (cnt_elm): log("Save Storehouse: size(%d)=[%d], ...", cnt_elm, cnt_bytes, ... поэтому не стОит дублировать одно и то же... Ну а по сути сообщения, то (ИМХО): 1. Конечно можно вслепую уменьшить полезный объем каждого элемента хранилища и успокоиться, если не возникнет в игре ошибок... Однако, если не ясна причина возникновения ошибки, то никто не гарантирует, что при некотором изменении в игре, ошибка все же не возникнет. Исправлять нужно причину. а не пытаться подстраиваться под ситуацию. А вот для этого ты поленился даже строки лога об ошибке указать. 2. Уверен, что если тебе приходится сохранять "строки по 90-130 байт ... порядка нескольких тысяч штук." - то с оптимизацией в твоем моде явно нелады. В сэйве обычно хранят эксклюзивную информацию, которая характеризует именно текущее состояние в игре, а не абы все и вся, что зачем-то захотелось записывать.
×
×
  • Создать...