Это популярное сообщение. Malandrinus 615 Опубликовано 8 Июля 2009 Это популярное сообщение. Поделиться Опубликовано 8 Июля 2009 (изменено) В данной теме собраны сведения по скриптовой модели сталкера: функции и классы, методы и свойства, взаимосвязь классов и последовательность работы с ними, связь работы классов и файлов конфигураций. К наполнению темы приглашаются все желающие. В наполнении темы непосредственно участвовали и существенно мне помогли: @Monnoroch, @Kolmogor, @Unnamed Black Wolf, @меченый(стрелок), @IQDDD, @Kirag, @Taroz, @dan, @7.9, @Garry_Galler, @AKKK1, @Bak и много других людей. Скрытый текст Скрытый текст класс alife_simulator. Базовые операции с серверными объектами. Пространства имён. Глобальные функции для большого числа задач. "Создание своего класса" и "Наследование от экспортированных классов". Базовые сведения об объектно-ориентированном программировании для сталкера. Необходимо прочитать, для понимания темы про биндер и некоторых других. В одном посте: Общие слова об архитектуре и скриптовой модели сталкера "Класс object_binder" расширение онлайновых объектов, колбеки, сохранение состояния. "Класс net_packet" Регистрация скриптовых классов с помощью object_factory Серверные классы. Часть 1 Иерархия серверных классов, описание не закончено. Серверные классы. Часть 2 Картинка структуры наследования и несколько заключительных слов Клиентские классы Скрытый текст Класс game_object Интерфейс ко всем онлайновым (клиентским объектам) Класс hit для нанесения урона скриптом и другая информация (IQDDD) Некоторая информация по управлению путями патрулирования здесь (Kirag) и здесь (Taroz) Неполная информация по управлению памятью неписей с примером здесь (Bak) Физическая оболочка объектов (Garry_Galler) Пост о выборе (подборе) оружия НПС и стрельбы (*Shoker*) Скрытый текст Управление заданиями Класс CGameTask и другие вспомогательные классы и функции. Управление инфопорциями Функции, колбеки, форматы файлов Список специальных системных инфопорций (Unnamed Black Wolf) Система профилей и алгоритм генерации имён. Форматы файлов, функции Дополнительная информация по параметрам профилей terrain_sect (Kolmogor) Диалоги. Часть 1 Форматы файлов, базовые сведения Диалоги. Часть 2 Скриптовые диалоги Диалоги. Часть 3 Тематическая подборка функций управления диалогами Скрытый текст Функции времени Тематическая подборка функций, связанных с управлением игровым временем. Класс CTime Вспомогательный класс для управления игровым временем Полезная скриптовая функция с использованием CTime (Garry_Galler) Скрытый текст class ini_file (меченый(стрелок)) Класс FS и CSavedGameWrapper Бинарный доступ к файлам, в том числе в игровых архивах, управление сохранёнными играми. Скрипт уровня. Забытая фишка с колбеком на заход на уровень Класс vector Некоторая полезная информация о разных вещах (меченый(стрелок)) "Класс render_device" Направление и положение камеры, характеристики экрана, программная пауза игры и др. Некоторая информация о различиях между ТЧ и ЗП в системе оконных классов и колбеков. (lekzd) Неплохо бы развить эту тему! Некоторая полезная информация о скриптовых функциях из модуля _g.script. (lekzd) Также требует развития! Полезные функции для работы с графом игры (Garry_Galler) В одном посте: Класс profile_timer Отладочные измерения скорости работы фрагментов программы Класс client_spawn_manager Колбек на выход в онлайн без использования биндера. Работа с консолью. Класс CConsole Анимации цвета. Класс color_animator Всякие моргающие элементы в окнах и пр. Управление постэффектами. Скриптовые постэффекты. Класс effector Класс sound_object. Проигрывание звуков в игре в произвольном месте, от произвольного объекта, в голове актора. (Shadows) Пост удалён автором (прим. Kirgudu) Скрытый текст Оконные классы Некоторая общая информация о создании окон Список методов, XML-тегов и событий для оконных классов (ТЧ/ЧН/ЗП) (Norman Eisenherz) Представление материала в моих статьях оптимизировано для онлайнового просмотра. Если кому не хочется лазить по спойлерам, а нужно просмотреть текст какого-либо поста "потоком", то могу рекомендовать просмотр в режиме "текстовая версия". В этом же режиме удобно сохранять содержимое темы на диск. (прим. Malandrinus) Изменено 30 Июля пользователем Kirgudu 5 5 16 Плагины Total Commander для работы с игровыми архивами: Архиваторный плагин (для работы с одиночным архивом): link1 link2 Системный плагин (для распаковки установленной игры): link1 link2 Ссылка на комментарий
Malandrinus 615 Опубликовано 25 Декабря 2009 Автор Поделиться Опубликовано 25 Декабря 2009 (изменено) Сначала в двух словах, как пользоваться механизмом выдачи заданий. Для выдачи задания есть метод класса game_object (естественно, это должен быть актор) void give_task( CGameTask* <задание>, -- подготовленный объект задания, см. далее int <время до истечения>, -- время от начального момента до истечения срока задания в ms boolean <проверять на наличие такого>) -- если true и задание с таким идентификатором уже есть, то не будет добавлено Комментарии: 1. Нетрудно посчитать, что в 32-х разрядное целое влазит миллисекунд примерно на месяц. Соответственно - это и будет максимально возможным временем для задания. 2. Третий параметр вероятно имеет смысл использовать для разных категорий заданий. Одноразовые квестовые должны иметь параметр true, а повторяющиеся однотипные - false Выдаём задания так: 1. Сначала надо подготовить объект типа CGameTask. Самый простой способ - воспользоваться уже готовыми заданиями, описанными в xml файлах. Для этого у класса CGameTask есть метод loadlocal new_task = CGameTask()new_task:load("gar_car_graveyard_quest") -- задание "Предложить помощь Бесу" 2. Собственно выдаём заданиеdb.actor:give_task(new_task, 3600*1000, true) -- срок выполнения 1 час, если уже выдано, то второй раз не получим Для получения статуса отдельной подзадачи задания есть метод класса get_task_state.enum ETaskState get_task_state(string <идентификатор задания>, int <номер подзадачи>) перечисление ETaskState экспортировано в виде класса task (см. далее) Пример использованияlocal task_status = db.actor:get_task_state("gar_car_graveyard_quest", 0) Для установки статуса отдельной подзадачи есть метод set_task_state:void set_task_state(enum ETaskState <статус>, string <идентификатор задания>, int <номер подзадачи>) -- если такого задания у актера нет, то выдаст ошибку Это всё было для уже готовых заданий. Если надо лепить задания скриптами, то необходимо использовать все возможности класса CGameTask. Далее я привожу описание классов CGameTask, вспомогательного класса SGameTaskObjective и task. Если кому это на самом деле надо, этого описания должно быть достаточно. C++ class CGameTask { CGameTask() -- конструктор. Как и для большинства классов, конструктор - это просто глобальная функция с именем класса, которая возвращает свежесозданный объект. void load(string) -- загрузить конфигурацию задачи из файла config\gameplay\game_tasks.xml -- этот файл содержит несколько инклюдов, так что фактически нужное описание может -- находиться и не в нём string get_id() -- даёт строку-идентификатор задачи. Это атрибут id из тега game_task в XML -- если не был выполнен метод load или не была добавлена хоть одна подзадача, то вернёт nil -- если вручную добавили подзадачу, то вернёт "user_task" SGameTaskObjective get_objective(number) -- получить параметры подзадачи по номеру -- каждая подзадача в xml-файле описывается отдельным тегом objective -- можно добавлять свои с помощью add_objective void add_objective(SGameTaskObjective*) -- добавить подзадачу int get_objectives_cnt() -- число подзадач string get_title() -- содержимое тега title или значение, установленное ранее set_title, -- или nil, если никак не инициализировали void set_title(string) -- установить заголовок задачи (внятное имя) }; Класс [b]SGameTaskObjective[/b] описывает одну подзадачу C++ class SGameTaskObjective { SGameTaskObjective (CGameTask*, number) -- загрузить подзадачу из конкретной задачи -- поскольку конструктора без аргументов нет, то выходит так, что сделать свою подзадачу -- полностью с нуля не получится. С другой стороны ничто не мешает взять из любой задачи -- произвольную подзадачу и изуродовать её по своему вкусу int get_idx() -- номер подзадачи в составе общей задачи int get_state() -- состояние подзадачи. Возвращает один из элементов перечисления task (см. далее) void set_description(string) -- установка имени подзадачи (точнее идентификатора, который -- ещё может быть сконвертирован в строку через механизм локализации) string get_description() -- даёт значение тега <text> или ранее установленное функцией set_description -- при выдаче задания будет тренькающий звук и на экране появится имя первой подзадачи -- (а не имя общей задачи, как можно было бы подумать). При этом, если в таблице строк есть -- строка с соответствующим идентификатором, то будет выдана именно эта строка -- если такой строки нет, то будет выдано исходное значение (иными словами все строки перед выводом -- проходят конвертацию с помощью функции game.translate_string()) void set_article_key(string) -- не знаю что такое void set_article_id(string <article_id>) -- установка статьи в PDA для подзадачи. -- эквивалентно значению тега <article> -- Будет отображаться в правой части PDA при просмотре информации о задании -- article_id должен быть зарегистрированной статьёй void set_object_id(number) -- вроде как story_id целевого объекта, определяет координаты метки void set_map_hint(string) -- надпись на метке (не проверял) void set_map_location(string) -- иконка (не проверял) -- с помощью указанных ниже функций можно добавлять предусловия и действия на успех и провал задач -- можно добавлять несколько -- инфопорция предусловия успешного завершение задачи, соответствует тегу "infoportion_complete" void add_complete_info(string); // -- скриптовая функция предусловия успешного завершение задачи, соответствует тегу "function_complete" void add_complete_func(string); -- инфопорция, выдаваяемая при успешном завершении задачи, соответствует тегу "infoportion_set_complete" void add_on_complete_info(string); -- скриптовая функция, выполняемая при успешном завершении задачи, соответствует тегу "function_call_complete" void add_on_complete_func(string); -- инфопорция предусловия провала задачи, соответствует тегу "infoportion_fail" void add_fail_info(string); -- скриптовая функция предусловия провала задачи, соответствует тегу "function_fail" void add_fail_func(string); -- инфопорция, выдаваяемая при провале задачи, соответствует тегу "infoportion_set_fail" void add_on_fail_info(string); -- скриптовая функция, выполняемая при провале задачи, соответствует тегу "function_call_fail" void add_on_fail_func(string); }; C++ class task { const fail = 0; const in_progress = 1; const completed = 2; const task_dummy = -1; }; Начиная с ЧН система заданий несколько изменилась. Исчезли подзадачи и соответственно перестал быть нужным класс SGameTaskObjective. Его методы по сути просто перешли в состав класса CGameTask. На мой взгляд всё стало проще, и если Вы поняли, как это работает в ТЧ, то экстраполировать это на ЧН и ЗП труда не составит. Изменено 29 Июля пользователем Kirgudu 1 1 Плагины Total Commander для работы с игровыми архивами: Архиваторный плагин (для работы с одиночным архивом): link1 link2 Системный плагин (для распаковки установленной игры): link1 link2 Ссылка на комментарий
lekzd 1 Опубликовано 29 Декабря 2009 Поделиться Опубликовано 29 Декабря 2009 А кто-нибудь знает как определить, что актор бежит? пока нашел способ определения по значению accuracy() но приходится подгонять его под каждое оружие метод сравнения координат актора "до" и "после" почему-то выдает резкие скачки значений, потому не подходит i-igroman.ru - Мой, принципиально новый сайт о компьютерных играх Ссылка на комментарий
Malandrinus 615 Опубликовано 30 Декабря 2009 Автор Поделиться Опубликовано 30 Декабря 2009 lekzd, можно попытаться по разнице между position и center. Это типа по наклону туловища =) Но там тоже нестабильные значения. Вообще-то по скорости не так уж и плохо работает. Если учесть, что апдейты идут нерегулярно и вычислять скорость по настоящему, т.е. учитывая параметр delta, то точность повышается. Также вроде как лучше вычислять скорость только с учётом координат xz, т.е. игнорировать вертикальную компоненту. Кроме того, можно ввести фильтрацию шума - усреднение по нескольким точкам. У меня усреднение по трём дало достаточно различимую картину: стоит, идёт, бежит. Но иногда таки бывают выбросы. По пяти точкам - различие практически идеальное. Хотя и появляется некоторая микроскопическая задержка, связанная с размазыванием переходов. Вопрос ещё, для чего это надо. Если скажем надо просто отобразить состояние бега на худе, то и так вполне сойдёт. Плагины Total Commander для работы с игровыми архивами: Архиваторный плагин (для работы с одиночным архивом): link1 link2 Системный плагин (для распаковки установленной игры): link1 link2 Ссылка на комментарий
lekzd 1 Опубликовано 31 Декабря 2009 Поделиться Опубликовано 31 Декабря 2009 malandrinus, я сделал полностью динамический ХУД и скрываю его во время бега при резких скачках он начинает "моргать" (значения резко скачут), что приводит к падению ФПС можешь привести код проверки по трем точкам? (я делал код проверки по x z + усреднение значений по двум точкам во времени) i-igroman.ru - Мой, принципиально новый сайт о компьютерных играх Ссылка на комментарий
Malandrinus 615 Опубликовано 4 Января 2010 Автор Поделиться Опубликовано 4 Января 2010 (изменено) Введение Скрытый текст При первом взгляде на lua_help.script возникает впечатление "дофига всего - объять нереально". Особенно это касается больших иерархий классов. Наиболее "развесистыми" являются три: оконные классы для создания пользовательского интерфейса и модификации элементов худа, серверные классы и клиентские классы для серверной и клиентской частей игровых объектов соответственно.Про оконные классы поговорим в другой раз, а сейчас займёмся серверными и клиентскими классами. Что потребуется:Первое. Необходимо представлять себе что такое классы и с чем их едят. Основное понятие, которое надо понимать - это наследование классов. Неплохо бы понимать идею базового класса и интерфейса.Второе. Необходимо достаточно хорошо понимать природу разделения классов на серверные и клиентские. Можете почитать мой трёп здесь в статье про object_binder.Третье. Вероятно имеет смысл почитать мою статью о реализации классов в сталкере.Четвёртое. Между серверными и клиентскими классами есть взаимосвязь. Кое что я попробую описать, кое-что уже описывал в статье о классе object_factory. Но это не полная информация.Пятое. Я вынужден ввести некоторые искусственные соглашения при описании классов. Это необходимо для сокращения объёма дублирующей информации. Внимательно прочитайте это вступление!Шестое. Информация приводится для Зова Припяти. Впрочем, отличия от ЧН и ТЧ минимальны. Я постарался пометить отличающиеся места, но где-то мог и не сделать этого. Смотрите внимательней!Наконец. Данное описание - это не то чтобы описание в полном смысле этого слова. Я не в состоянии описать в одиночку более сотни классов и несколько сотен методов и свойств. Это скорее попытка привести в некоторую систему помойку из lua_help, убрать смысловой шум и создать основу для дальнейшего полного описания. Я постарался дать по возможности точную информацию о типах аргументов и возвращаемых значений функций, но назначение их не описано. Итак. Все игровые сущности (сталкеры, монстры, предметы и пр.) в общем случае существуют одновременно на двух сторонах - на сервере и на клиенте. На каждой стороне для этого есть соответствующие классы. На серверной - это классы, имя которых начинается на "cse". С некоторыми поправками можно считать, что все серверные классы происходят от cse_abstract. На клиентской стороне есть соответствующая иерархия классов. Можно считать, что все они происходят от CGameObject. На клиентской стороне есть ещё и game_object, который также является интерфейсом к клиентским объектам, причём основным интерфейсом. Его описание уже начато, но оно далеко от завершения.Классы как серверные, так и клиентские образуют иерархию наследования классов. На самом примитивном уровне можно считать, что наследование означает включение всех членов базового класса (т.е. свойств и методов) в производный класс. В свою очередь это означает, что нет необходимости описывать унаследованные члены для всех производных классов, достаточно это сделать один раз для базового. Кроме того я ввожу важное соглашение для описания классов: я не буду приводить полный список членов класса для каждого из них, а только список методов и свойств, которые добавляет конкретный класс сверх унаследованных. Поэтому, если по описанию в классе нет ничего, то смотрите на классы от которых он унаследован и смотрите список их методов и список методов их базовых классов и т.д. Я вынужден так сделать во-первых в силу ограничения форума, во вторых для убирания избыточности при описании. Я также буду пользоваться спойлерами: после описания класса будет идти спойлер с его производными классами, в них спойлеры с их производными и т.д. (наподобие матрёшки =)Начнём с серверных.Можно обратить внимание, что имеется некоторое количество базовых классов и интерфейсов, которые вообще не содержат никаких методов или свойств. Наследование от них не даёт конкретной информации о свойствах серверного класса, но парадоксальным образом может дать некоторые догадки о применимости методов game_object. Вот список этих базовых интерфейсов: Базовые интерфейсы Скрытый текст // все приведённые интерфейсы не содержат ни методов ни свойств, поэтому // приводится только их список и отношение их наследования // в принципе, можно погадать и на тему ipure_alife_load_object ipure_alife_save_object ipure_alife_load_save_object : ipure_alife_load_object,ipure_alife_save_object ipure_server_object : ipure_alife_load_save_object cpure_server_object : ipure_server_object // все вообще классы наследованы от cpure_server_object, // его можно описать, как "объект, который умеет сохраняться и восстанавливать своё состояние" ipure_schedulable_object cse_alife_schedulable : ipure_schedulable_object // класс cse_alife_schedulable - это вроде как объекты, с которыми работает планировщик cse_visual // для этих объектов нужна модель. Их "видно" cse_motion // эти объекты умеют двигаться cse_ph_skeleton // у этих есть кости cse_shape // вроде как объекты, с которыми связана некоторая область пространства: аномалии, смарты и т.п. cse_alife_group_abstract // без понятия, зачем нужен cse_alife_inventory_item // объекты, которые можно взять в инвентарь // этот интерфейс является некоторым исключением, поскольку содержит методы // судя по использованию отвечает за возможность торговать: актор и сталкеры C++ class cse_alife_trader_abstract { string profile_name(); int reputation(); int rank(); int community() const; }; Несколько предваряющих комментариев к дальнейшему материалу. Скрытый текст 1. Почти каждый из описанных классов имеет конструктор, который по традиции языка C++ имеет имя, совпадающее с именем класса, и не возвращает никакого значения. У каждого объекта из иерархии cse_abstractвсего один конструктор, который всегда принимает один аргумент - строку. Очевидно, что аргумент - это имя секции из system.ltx. Как и для остальных классов, экспортированных с помощью технологии Luabind, это означает, что имеется глобальная функция с именем класса, которая принимает такие же аргументы, как и конструктор, и возвращает объект класса. И такие функции на самом деле есть для каждого серверного класса. Однако попытка их вызвать у меня лично приводит к неизменному вылету. Так и должно быть! Серверные объекты создаются опосредованно, с помощью вызова метода create класса alife_simulator. См. эту статью.Итак, конструктор всегда один, имеет определённое имя и один и тот-же аргумент, да и толку от него нет. Кроме того, его наличие в составе класса - вообще изрядная условность, поскольку он не внутри класса, а снаружи. Так что в качестве дополнительного соглашения, позволяющего экономить пространство форума, я не буду приводить эти конструкторы в описании классов.Если класс не добавляет ничего к базовому, то ради экономии места его пишу по сокращённому варианту - одной строкой с указанием только его имени и базовых классов.2. Серверные классы - это классы экспортированные таким образом, что на их основе можно создавать свои скриптовые классы. Опять же см. эту статью. Примеры таких скриптовых классов в игре можно найти в файлах, которые в основном начинаются с "se_": se_artefact.script, se_item.script и т.д. Вся иерархия серверных классов Скрытый текст class cse_abstract : cpure_server_object { vector* angle; // начиная с ЗП int id; int parent_id; vector* position; int script_version; void UPDATE_Read(net_packet&); void STATE_Read(net_packet&, number); string name(const cse_abstract*); void UPDATE_Write(net_packet&); void STATE_Write(net_packet&); int clsid() const; ini_file* spawn_ini(); string section_name(); cse_abstract* init(); // // FillProps и OnEvent начиная с ЧН убраны void FillProps(string, class xr_vector<class PropItem *,class xalloc<class PropItem *> >&); void OnEvent(net_packet&, number, number, ClientID); }; От класса cse_abstract унаследованы ВСЕ остальные классы. Иногда примешиваются дополнительные интерфейсы. Список классов унаследованных от cse_abstract Скрытый текст class cse_alife_graph_point : cse_abstract // так выглядит сокращённое описание, класс ничего не добавляет к родительскомуclass cse_spectator : cse_abstractclass cse_temporary : cse_abstractclass cse_alife_object_climable : cse_shape,cse_abstract class CSE_AbstractVisual : cse_visual,cse_abstract { string getStartupAnimation(); // добавлен всего один метод. }; class cse_alife_object : cse_abstract { int m_game_vertex_id; int m_level_vertex_id; int m_story_id; bool online; bool used_ai_locations() const; ??void?? use_ai_locations(boolean); // начиная с ЗП bool can_save() const; bool can_switch_online() const; void can_switch_online(boolean); bool interactive() const; bool visible_for_map() const; void visible_for_map(boolean); bool can_switch_offline() const; void can_switch_offline(boolean); bool move_offline() const; void move_offline(boolean); }; От класса cse_alife_object унаследован всего один класс cse_alife_dynamic_object, так что нет смысла прятать его под спойлер. class cse_alife_dynamic_object : cse_alife_object { void switch_offline(); void switch_online(); bool keep_saved_data_anyway() const; // либо synchronize_location, либо redundant void on_spawn(); void on_before_register(); void on_register(); void on_unregister(); }; Список классов, унаследованных от cse_alife_dynamic_object Скрытый текст class cse_alife_space_restrictor : cse_alife_dynamic_object,cse_shape Список классов, унаследованных от cse_alife_space_restrictor Скрытый текст class cse_alife_level_changer : cse_alife_space_restrictorclass cse_alife_team_base_zone : cse_alife_space_restrictor class cse_alife_smart_zone : cse_alife_space_restrictor,cse_alife_schedulable { float detect_probability(); void smart_touch(cse_alife_monster_abstract*); void unregister_npc(cse_alife_monster_abstract*); void update(); // явно идёт от cse_alife_schedulable function register_npc(cse_alife_monster_abstract*); float suitable(cse_alife_monster_abstract*) const; CALifeSmartTerrainTask* task(cse_alife_monster_abstract*); bool enabled(cse_alife_monster_abstract*) const; }; class cse_alife_online_offline_group : cse_alife_dynamic_object,cse_alife_schedulable { // все методы класса экспортированы только начиная с ЗП void update(); void register_member(number); void unregister_member(number); function clear_location_types(); function get_current_task(); function commander_id(); function squad_members() const; function force_change_position(vector); function add_location_type(string); ??int?? npc_count() const; }; class cse_smart_cover : cse_alife_dynamic_object { function description() const; function set_available_loopholes(object); }; class cse_custom_zone : cse_alife_dynamic_object,cse_shape Список классов, унаследованных от cse_custom_zone Скрытый текст class cse_torrid_zone : cse_custom_zone,cse_motion class cse_anomalous_zone : cse_custom_zone class cse_zone_visual : cse_anomalous_zone,cse_visual class cse_alife_dynamic_object_visual : cse_alife_dynamic_object,cse_visual Список классов, унаследованных от cse_alife_dynamic_object_visual Скрытый текст class cse_alife_car : cse_alife_dynamic_object_visual,cse_ph_skeleton class cse_alife_helicopter : cse_alife_dynamic_object_visual,cse_motion,cse_ph_skeleton// класс cse_alife_inventory_box появился в ЗПclass cse_alife_inventory_box : cse_alife_dynamic_object_visual class cse_alife_mounted_weapon : cse_alife_dynamic_object_visual class cse_alife_object_breakable : cse_alife_dynamic_object_visual class cse_alife_object_hanging_lamp : cse_alife_dynamic_object_visual,cse_ph_skeleton class cse_alife_object_physic : cse_alife_dynamic_object_visual,cse_ph_skeleton class cse_alife_object_projector : cse_alife_dynamic_object_visual class cse_alife_ph_skeleton_object : cse_alife_dynamic_object_visual,cse_ph_skeleton class cse_alife_trader : cse_alife_dynamic_object_visual,cse_alife_trader_abstract class cse_alife_creature_abstract : cse_alife_dynamic_object_visual { int team; int group; int squad; void on_death(cse_abstract*); bool alive() const; int g_team(); int g_group(); int g_squad(); float health() const; // o_torso появилась начиная с ЧН Rotation o_torso(); }; Список классов, унаследованных от cse_alife_creature_abstract Скрытый текст class cse_alife_creature_actor : cse_alife_creature_abstract,cse_alife_trader_abstract,cse_ph_skeletonclass cse_alife_creature_crow : cse_alife_creature_abstract // начиная с ЧНclass cse_alife_creature_phantom : cse_alife_creature_abstract // начиная с ЧН class cse_alife_monster_abstract : cse_alife_creature_abstract,cse_alife_schedulable { // начиная с ЗП int group_id; // начиная с ЧН int m_smart_terrain_id; function kill(); // начиная с ЗП void update(); function force_set_goodwill(number, number); // начиная с ЗП function clear_smart_terrain(); float travel_speed(); // начиная с ЧН void travel_speed(float); // начиная с ЧН function smart_terrain_task_deactivate(); function smart_terrain_task_activate(); float current_level_travel_speed(); // начиная с ЧН void current_level_travel_speed(float); // начиная с ЧН CALifeMonsterBrain* brain(); bool has_detector(); // начиная с ЗП int smart_terrain_id(); // всегда тоже самое, что и m_smart_terrain_id int rank(); }; Список классов, унаследованных от cse_alife_monster_abstract Скрытый текст class cse_alife_monster_rat : cse_alife_monster_abstract,cse_alife_inventory_item class cse_alife_monster_zombie : cse_alife_monster_abstract class cse_alife_monster_base : cse_alife_monster_abstract,cse_ph_skeleton class cse_alife_psydog_phantom : cse_alife_monster_base class cse_alife_human_stalker : cse_alife_human_abstract,cse_ph_skeleton class cse_alife_human_abstract : cse_alife_trader_abstract,cse_alife_monster_abstract { // rank из интерфейса cse_alife_trader_abstract конфликтует с такой же из cse_alife_monster_abstract // непонятно, какая из них "побеждает" и непонятно, к чему тогда относится вот эта void set_rank(int); // }; class cse_alife_item : cse_alife_dynamic_object_visual,cse_alife_inventory_item { bool bfUseful(); }; Список классов, унаследованных от cse_alife_item Скрытый текст class cse_alife_item_ammo : cse_alife_item class cse_alife_item_artefact : cse_alife_item class cse_alife_item_bolt : cse_alife_item class cse_alife_item_custom_outfit : cse_alife_item class cse_alife_item_detector : cse_alife_item class cse_alife_item_document : cse_alife_item class cse_alife_item_explosive : cse_alife_item class cse_alife_item_grenade : cse_alife_item class cse_alife_item_pda : cse_alife_item class cse_alife_item_torch : cse_alife_item class cse_alife_item_weapon : cse_alife_item { // clone_addons появилась в ЗП function clone_addons(cse_alife_item_weapon*); }; // иерархия наследования от cse_alife_item_weapon простая, так что без спойлера// класс cse_alife_item_weapon_auto_shotgun появился в ЗПclass cse_alife_item_weapon_auto_shotgun : cse_alife_item_weapon class cse_alife_item_weapon_magazined : cse_alife_item_weapon class cse_alife_item_weapon_magazined_w_gl : cse_alife_item_weapon_magazined class cse_alife_item_weapon_shotgun : cse_alife_item_weapon Изменено 29 Июля пользователем Kirgudu Плагины Total Commander для работы с игровыми архивами: Архиваторный плагин (для работы с одиночным архивом): link1 link2 Системный плагин (для распаковки установленной игры): link1 link2 Ссылка на комментарий
Malandrinus 615 Опубликовано 5 Января 2010 Автор Поделиться Опубликовано 5 Января 2010 (изменено) Полагаю, красивая картинка никому не помешает. Вот вам диаграмма серверных классов с высоты птичьего полёта =) Обращаю внимание на нотацию записи: большая пустая стрелка означает отношение обобщения (или наследования иными словами) и направлена от унаследованного класса к базовому. Включение абстрактного интерфейса обозначается стрелкой с кружочком и указанием, какой интерфейс наследуется. Это сокращённая форма записи, позволяющая избавиться от нагромождения линий и лучше понять основную линию наследования. С серверными классами пока всё. Некоторые выводы по данному этапу. 1. Большинство классов не добавляют новых методов и свойств. В целом, информации существенно меньше, нежели кажется на первый взгляд. 2. Между ТЧ, ЧН и ЗП не так уж и много отличий. Хотя отличия имеются: добавлено несколько новых классов, изрядно добавлено новых методов в существующих классах и пара методов исчезла. 3. Я не описывал ни назначение классов, ни назначение их методов. В некоторых местах (в основном для новых методов в ЧН и ЗП) не удалось пока получить информации о параметрах и возвращаемых значениях. Наверняка где-то упустил продокументировать различие между играми. В принципе, практически все методы классов до cse_alife_object включительно известны, как и некоторые из остальных классов. Однако у меня сейчас нет возможности заниматься документированием каждого из нескольких десятков методов. Надеюсь на помощь сообщества. Продолжение следует... Изменено 5 Января 2010 пользователем malandrinus Плагины Total Commander для работы с игровыми архивами: Архиваторный плагин (для работы с одиночным архивом): link1 link2 Системный плагин (для распаковки установленной игры): link1 link2 Ссылка на комментарий
7.9 174 Опубликовано 7 Января 2010 Поделиться Опубликовано 7 Января 2010 (изменено) Просто наблюдение: Разница между значениями game.time() и game.get_game_time()" - заметил, что при старте новых игр она каждый раз разная, и где-то, после 40млн.милисекунд, при рестарте счётчика, её значение изменяется... как ты высчитываешь разницу?Стартовал новую игру, получал game.time() и game.get_game_time(), переводил game.get_game_time() в мсек, вычитал и смотрел разницу. И какой рестарт счётчика ты имеешь в виду? Тот, что раз в месяц?Разница, была статична до того как, через какое-то игровое время, значение game.time() сбросилось и продолжило счёт с нуля, разница то-же пересчиталась и стала другой. Вот насчёт 40 млн... это я визуально запомнил - это может и не так быть, но срок был, в роде больше месяца, намного. Надо повторить эксперимент, а то вдруг чего не так делал... перепроверю. Но то, что game.time() обнулялась - это точно. Изменено 1 Декабря 2010 пользователем 7.9 всё легко Ссылка на комментарий
Malandrinus 615 Опубликовано 7 Января 2010 Автор Поделиться Опубликовано 7 Января 2010 (изменено) 7.9, всё верно, только не 40 млн., а 4 мрд., точнее максимальное 32-х разрядное беззнаковое целое: 4294967295 что в миллисекундах составляет примерно 1193 часа, т.е. 49 дней. Это известная проблема: после примерно месяца игрового времени часть функций, связанных с использованием этого счётчика, начинают работать неправильно. Вроде как это даже лечили. Хотя если этот счётчик используется не только скриптами, но и движком, то всё не вылечить. Изменено 13 Января 2010 пользователем malandrinus Плагины Total Commander для работы с игровыми архивами: Архиваторный плагин (для работы с одиночным архивом): link1 link2 Системный плагин (для распаковки установленной игры): link1 link2 Ссылка на комментарий
Malandrinus 615 Опубликовано 8 Января 2010 Автор Поделиться Опубликовано 8 Января 2010 (изменено) Разбираем систему клиентских классов. Сначала немного лирики. Скрытый текст Итак, на клиентской стороне есть своя иерархия классов, отвечающих за онлайновые (т.е. клиентские) объекты. Все они унаследованы от CGameObject. Дерево наследования там не столь сложное, как для серверных классов. Тем не менее для каждого (почти) типа игровых объектов есть свой класс, и при первом взгляде всё смотрится вполне прилично. Но это только на первый взгляд. При более внимательном рассмотрении выясняется, что классы хоть и есть, но добраться до произвольного клиентского объекта невозможно. Т.е. нет никаких функций, с помощью которых можно было бы получить произвольный клиентский объект, производный от CGameObject. Соответственно, нет и возможности вызывать их методы. Кроме того, эти классы не предназначены для создания на их основе скриптовых классов. Таким образом, все общие пути для использования объектов этого класса закрыты. Соответственно, основным и почти единственным интерфейсом к объектам на клиентской стороне остаётся game_object. Однако не всё так трагично =) Есть исключения. Если в классе добавлены какие-либо методы сверх основного набора из CGameObject, то для получения объектов такого класса в game_object имеются специальные методы. В ТЧ исходно всего три таких класса: CCar, CHelicopter и hanging_lamp. Соответственно в game_object есть методы:get_car() - для CCarget_helicopter() - для CHelicopterget_hanging_lamp() - для hanging_lampВ ЧН методы добавлены в классы CPhysicObject, CArtefact, CZoneCampfire и CAI_Bloodsucker. Соответственно появились и новые методы в game_object: get_physics_object(), get_artefact() и get_campfire(). А вот для кровососа почему-то функции нет.К этому могу добавить, что посмотрев на состав методов CGameObject, можно увидеть их сходство с набором методов object_binder. Таким образом скорее всего методы CGameObject опосредованно доступны через биндер. Для тех, что недоступны, вроде как имеются некие аналоги в game_object, и даже для работы с визуалом похоже начиная с ЗП появились функции (но это неподтверждённая информация).Наконец надо заметить, что главным использованием системы этих классов является не прямое использование, а опосредованное - через механизм регистрации скриптовых серверных классов. Я об этом рассказывал здесь, рекомендую почитать. Возможность регистрации своего скриптового серверного класса определяется наличием соответствующего ему экспортированного клиентского. Достаточно, чтобы он просто был. И вот как раз здесь имеется приличный прорыв: по сравнению с ТЧ в ЧН и ЗП добавлено много новых классов - теперь охвачены почти все игровые объекты (почти, но таки не все).Теперь можно делать скриптовые серверные классы для ящиков, PDA, аддонов и аномалий. В первую очередь это означает, что теперь можно без проблем хранить серверное состояние этих объектов, что существенно облегчает создание модов, где эти объекты используются в оффлайне. Также добавлен актор, что означает возможность сделать серверного актора. Как-то это используется в игре. Довольно лирики. Далее представлена система клиентских классов. Используются те-же соглашения, что и раньше: конструктор не показан, если класс не добавляет своих методов, то показан одной строкой. Иерархия клиентских классов Сперва базовые интерфейсы. Их не так много, как у серверных. Скрытый текст class DLL_Pure { DLL_Pure* _construct(); }; Как будет видно далее, на самом деле самым базовым классом является DLL_Pure. Похоже, что именно этот класс является необходимым для механизма регистрации скриптовых классов. Есть ещё классы, не относящиеся к игровым объектам, но унаследованные от DLL_Pure, которые тоже можно использовать с классом object_factory.ICollidableIRenderableISheduledНепосредственно от DLL_Pure наследованы всего три класса.class ce_smart_zone : DLL_Pureclass ce_script_zone : DLL_Pure class CGameObject : DLL_Pure,ISheduled,ICollidable,IRenderable { ??string?? Visual() const; function getEnabled() const; void net_Export(net_packet&); void net_Import(net_packet&); function getVisible() const; int net_Spawn(cse_abstract*); bool use(CGameObject*); }; Все остальные классы имеют своим предком CGameObject Классы, производные от CGameObject Скрытый текст CActor // начиная с ЧНCAI_StalkerCAI_Trader// монстры class CAI_Bloodsucker : CGameObject { function force_visibility_state(number); }; CAI_Boar CAI_Dog CAI_Flesh CAI_PseudoDog CBurer CCat CChimera CController CFracture CPoltergeist CPseudoGigant CPsyDog CPsyDogPhantom CSnork CTushkano CZombie//съедаемые предметыCAntirad CBottleItem CFoodItem CMedkit//устройстваCTorchCSimpleDetector -- класс есть, но не документирован в lua_helpCAdvancedDetector -- класс есть, но не документирован в lua_helpCEliteDetector -- класс есть, но не документирован в lua_helpCScientificDetector -- класс есть, но не документирован в lua_help//аддоныCGrenadeLauncher CScope CSilencer//разные объекты hanging_lamp Скрытый текст class hanging_lamp : CGameObject { hanging_lamp (); void turn_on(); void turn_off(); }; CCar Скрытый текст class holder { bool engaged(); void Action(int, int); void SetParam(int, vector); }; class CCar : CGameObject,holder { // CCarWeapon::__unnamed const eWpnDesiredDir = 1; const eWpnDesiredPos = 2; const eWpnActivate = 3; const eWpnFire = 4; const eWpnAutoFire = 5; const eWpnToDefaultDir = 6; CCar (); float GetfHealth() const; float SetfHealth(float); vector CurrentVel(); bool IsObjectVisible(game_object*); int ExplodeTime(); void SetExplodeTime(int); bool HasWeapon(); float FireDirDiff(); void CarExplode(); bool CanHit(); }; CHelicopter Скрытый текст class CHelicopter : CGameObject { //EHeliState const eAlive = 0; const eDead = 1; //EHeliBodyState const eBodyByPath = 0; const eBodyToPoint = 1; //EHeliHuntState const eEnemyNone = 0; const eEnemyPoint = 1; const eEnemyEntity = 2; //EHeilMovementState const eMovNone = 0; const eMovToPoint = 1; const eMovPatrolPath = 2; const eMovRoundPath = 3; const eMovLanding = 4; const eMovTakeOff = 5; bool m_dead; bool m_exploded; bool m_flame_started; bool m_light_started; float m_max_mgun_dist; float m_max_rocket_dist; float m_min_mgun_dist; float m_min_rocket_dist; bool m_syncronize_rocket; int m_time_between_rocket_attack; bool m_use_mgun_on_attack; bool m_use_rocket_on_attack; CHelicopter (); void Die(); // красиво падать, потом взорваться void Explode(); // сразу взорваться float GetfHealth() const; float SetfHealth(float); EHeliHuntState GetHuntState(); EHeliBodyState GetBodyState(); EHeilMovementState GetMovementState(); ??EHeliState?? GetState(); void ClearEnemy(); // ни в кого не стрелять function SetEnemy(game_object*); // в кого стрелять function SetEnemy(vector*); // куда стрелять float GetCurrVelocity(); vector GetCurrVelocityVec(); float GetMaxVelocity(); void SetMaxVelocity(float); float GetDistanceToDestPosition(); float GetOnPointRangeDist(); float GetRealAltitude(); // абсолютная высота float GetSafeAltitude(); float GetSpeedInDestPoint(number); void SetSpeedInDestPoint(float); void SetBarrelDirTolerance(float); function SetLinearAcc(number, number); void GoPatrolByPatrolPath(string, int); void GoPatrolByRoundPath(vector, float, boolean); bool isVisible(game_object*); void LookAtPoint(vector, boolean); // развернуться носом в точку void SetDestPosition(vector*); // куда лететь bool UseFireTrail(); void UseFireTrail(boolean); void SetFireTrailLength(float); void SetOnPointRangeDist(float); void StartFlame(); // начать гореть void TurnEngineSound(boolean); // звук двигателя void TurnLighting(boolean); // включить прожектор }; CPhysicObject Скрытый текст class CPhysicObject : CGameObject { function anim_time_get(); function anim_time_set(number); function play_bones_sound(); function run_anim_back(); function run_anim_forward(); function set_door_ignore_dynamics(); function stop_anim(); function stop_bones_sound(); function unset_door_ignore_dynamics(); }; CDestroyablePhysicsObject CExplosiveItem CWeaponAmmoCInventoryBox CPda//ГранатыCF1 CRGD5//оружиеCWeaponAK74 CWeaponAutomaticShotgun CWeaponBinoculars CWeaponBM16 CWeaponFN2000 CWeaponFORT CWeaponGroza CWeaponHPSA CWeaponKnife CWeaponLR300 CWeaponPM CWeaponRG6 CWeaponRPG7 CWeaponShotgun CWeaponSVD CWeaponSVU CWeaponUSP45 CWeaponVal CWeaponVintorez CWeaponWalther//аномалииCMincer CMosquitoBald CHairsZone CRadioactiveZone CTorridZone// Разные области class CZoneCampfire : CGameObject { function is_on(); function turn_on(); function turn_off(); }; CLevelChanger CSpaceRestrictor smart_cover_object//ШкуркиCStalkerOutfitCHelmet -- класс есть, но не документирован в lua_help Артефакты Скрытый текст class CArtefact : CGameObject { function SwitchVisibility(boolean); function FollowByPath(string, number, vector); function GetAfRank() const; }; Производные от CArtefactCBastArtefact CBlackDrops CBlackGraviArtefact CDummyArtefact CElectricBall CFadedBall CGalantineArtefact CGraviArtefact CMercuryBall CRustyHairArtefact CThornArtefact CZudaArtefact Рисовать картинку с иерархией наследования смысла нет, поскольку и так всё довольно очевидно. За исключением малого числа классов остальные к CGameObject ничего не добавляют. Соответственно и описывать нечего. Названия классов более или менее говорят о том, для каких объектов они предназначены. Где мог, указал точные сигнатуры функций (CCar, CHelicopter и hanging_lamp). Для новых классов и методов по сравнению с ТЧ такой информации к сожалению нет.Несколько рассуждений на тему взаимодействия серверного и клиентского объектов. Попробуем рассуждать логически. Есть сервер, есть клиент. Это в общем случае разные компьютеры. Каким может быть взаимодействие объектов, находящихся по разную сторону сети? Могут ли они, к примеру, вызывать методы друг друга, или непосредственно читать данные своего "напарника"? Очевидно нет. Моё мнение такое, что их взаимодействие сводится в основном к посылке данных друг другу. При этом, данные посылаются "пачкой", т.е. обо всём состоянии сразу. То, что я наблюдал, выглядит так: при переходе в онлайн создаётся клиентский объект, серверный его инициализирует, посылая ему при создании нетпакет. Этот момент можно отловить в биндере клиентского класса. Все дальнейшие движения происходят от клиентского объекта к серверному. Это означает, что периодически клиентский затирает данные серверного. Точные моменты, когда это происходит, периодичность, а также механизм передачи данных мне лично понять пока не удалось. По крайней мере на серверной стороне ничего не видно, просто тихо меняются данные, и понять, когда это происходит, крайне непросто.Однако некоторые выводы таки можно сделать. Если взаимодействие классов примерно такое, как я здесь предположил, то совместимость классов определяется совместимостью бинарных данных, которые они друг другу посылают. Ну в общем классы должны друг другу соответствовать, хотя, как далее будет видно, это правило на практике (очень редко) нарушается. Если не забыли ещё, то зарегистрированные пары классов задаются идентификаторами класса. В файлах конфигурации (в секциях объектов) этим идентификаторам соответствует параметр class. В скриптах - это один из членов clsid. В движке уже зарегистрированы соответствующие пары классов, и вы можете добавлять свои пары с помощью класса object_factory. Я это всё описывал здесь.Далее я привожу таблицу соответствия классов. Для полноты картины в ней указаны классы, которые не экспортированы в Lua. Если класс не экспортирован, то это означает, что вам не удастся зарегистрировать на его основе свою пару классов. Однако это не мешает (теоретически) создавать объекты этого класса при условии, что имеется и известен его идентификатор.Приведённая таблица собрана из разных источников, в том числе основана на примерах регистрации классов из игры. Видно, что иногда клиентский класс использует в качестве "напарника" серверный, который является базовым для своего "родного" серверного. Видимо, это технически в норме вещей и так можно поступать и нам. Из этого ряда выбивается CZombie, для которого вроде бы родным должен быть серверный класс cse_alife_monster_zombie, а регистрируют его с cse_alife_monster_base. Это вроде как нарушает вышеописанную логику, поскольку cse_alife_monster_base не является базовым для cse_alife_monster_zombie. С другой стороны, он так зарегистрирован в самом движке. Возможно cse_alife_monster_zombie попросту не задействован и никакого отношения к CZombie на самом деле не имеет. Таблица соответствия серверных и клиентских классов Скрытый текст Серверный класс | Клиентский класс ---------------------------------------+------------------------------------------------- cse_abstract | cse_alife_graph_point | cse_spectator | CSpectator -- не экспортированный класс cse_temporary | CExplosiveRocket -- не экспортированный класс cse_alife_object_climable | CClimableObject -- не экспортированный класс CSE_AbstractVisual | cse_alife_object | cse_alife_dynamic_object | cse_smart_cover | smart_cover_object cse_alife_online_offline_group | cse_custom_zone | CCustomZone -- не экспортированный класс cse_alife_space_restrictor | ce_smart_zone -- cse_alife_space_restrictor - это базовый | для cse_alife_smart_zone | видимо так можно делать | CSpaceRestrictor | ce_script_zone cse_alife_dynamic_object_visual | CScriptObject -- не экспортированный класс cse_alife_creature_abstract | cse_alife_inventory_box | CInventoryBox cse_alife_mounted_weapon | cse_alife_object_breakable | CBreakableObject -- не экспортированный класс cse_alife_object_projector | CProjector -- не экспортированный класс cse_alife_item | CAntirad | CBottleItem | CFoodItem | CMedkit | CGrenadeLauncher | CScope | CSilencer | CInventoryItemObject -- не экспортированный класс | CMPPlayersBag -- не экспортированный класс | CFlare -- не экспортированный класс cse_alife_trader | CAI_Trader cse_alife_helicopter | CHelicopter cse_alife_car | CCar cse_alife_object_hanging_lamp | hanging_lamp cse_alife_object_physic | CDestroyablePhysicsObject | CPhysicObject cse_alife_ph_skeleton_object | CPhysicsSkeletonObject -- не экспортированный класс cse_alife_creature_crow | CAI_Crow -- не экспортированный класс cse_alife_creature_phantom | CPhantom -- не экспортированный класс cse_alife_creature_actor | CActor cse_alife_monster_abstract | cse_alife_monster_zombie | CZombie -- вроде должен быть здесь cse_alife_monster_rat | CAI_Rat -- не экспортированный класс cse_alife_monster_base | CAI_Bloodsucker | CAI_Boar | CAI_Dog | CAI_Flesh | CAI_PseudoDog | CBurer | CCat | CChimera | CController | CFracture | CPoltergeist | CPseudoGigant | CPsyDog | CPsyDogPhantom | CSnork | CTushkano | CZombie -- это нарушает логику. | cse_alife_monster_base - не базовый для cse_alife_monster_zombie cse_alife_psydog_phantom | CPsyDogPhantom // должно быть так, вместо | этого записан в cse_alife_monster_base cse_alife_human_abstract | cse_alife_human_stalker | CAI_Stalker cse_alife_item_ammo | CWeaponAmmo cse_alife_item_artefact | CElectricBall | CBastArtefact | CBlackDrops | CBlackGraviArtefact | CDummyArtefact | CFadedBall | CGalantineArtefact | CGraviArtefact | CMercuryBall | CRustyHairArtefact | CThornArtefact | CZudaArtefact | CtaGameArtefact -- не экспортированный класс cse_alife_item_bolt | CBolt -- не экспортированный класс cse_alife_item_custom_outfit | CStalkerOutfit | CScientificOutfit -- не экспортированный класс | CMilitaryOutfit -- не экспортированный класс | CExoOutfit -- не экспортированный класс cse_alife_item_helmet | CHelmet cse_alife_item_detector | CAdvancedDetector | CEliteDetector | CScientificDetector | CSimpleDetector cse_alife_item_document | CInfoDocument -- не экспортированный класс cse_alife_item_explosive | CExplosiveItem cse_alife_item_grenade | CF1 | CRGD5 cse_alife_item_pda | CPda cse_alife_item_torch | CTorch cse_alife_item_weapon | CWeaponKnife cse_alife_item_weapon_auto_shotgun | CWeaponAutomaticShotgun cse_alife_item_weapon_magazined | CWeaponBinoculars | CWeaponHPSA | CWeaponLR300 | CWeaponMagazined | CWeaponPM | CWeaponRPG7 | CWeaponSVD | CWeaponSVU | CWeaponUSP45 | CWeaponVal | CWeaponVintorez | CWeaponWalther | CWeaponMagazined -- не экспортированный класс | CWeaponFORT -- не экспортированный класс cse_alife_item_weapon_shotgun | CWeaponBM16 | CWeaponRG6 | CWeaponShotgun cse_alife_item_weapon_magazined_w_gl | CWeaponAK74 | CWeaponGroza | CWeaponFN2000 | CWeaponMagazinedWGrenade -- не экспортированный класс cse_alife_level_changer | CLevelChanger cse_alife_team_base_zone | CTeamBaseZone -- не экспортированный класс cse_alife_smart_zone | ce_smart_zone cse_anomalous_zone | CMincer | CMosquitoBald | CRadioactiveZone | CNoGravityZone -- не экспортированный класс | CZoneCampfire cse_zone_visual | CHairsZone cse_torrid_zone | CTorridZone CSE_ALifeStationaryMgun | CWeaponStatMgun -- не экспортированный класс -- серверный также не экспортирован | Изменено 17 Декабря 2017 пользователем Murarius Плагины Total Commander для работы с игровыми архивами: Архиваторный плагин (для работы с одиночным архивом): link1 link2 Системный плагин (для распаковки установленной игры): link1 link2 Ссылка на комментарий
Kolmogor 5 Опубликовано 8 Января 2010 Поделиться Опубликовано 8 Января 2010 (изменено) Вот этот залипон со счётчиком времени - это совершенно типичный пример. И ведь игра заведомо создавалась, как шутер с элементами РПГ. Т.е. подразумевалось, что игрок будет исследовать локации, возвращаться на них, чтобы доделать квесты и прочее в этом роде. Учитывая дефолтовое соотношение игрового времени к реальному десять (!) 49 дней с легкостью превращаются всего в 5 дней реального игрового времени. Пять дней?! Для РПГ?! Смешно даже. И что мешало разрабам просто взять и посчитать, на сколько хватит этого счётчика? В движке в классе CTime 64х-разрядный счетчик и считает он нормально. Вообще вокруг этой проблемы слишком много шума. В оригинальной игре я ее не встречал. Видел только в АМК моде, но там использовали функцию level.get_time_days(), которая возвращает день месяца. Отсюда и пошла проблема 1 июня. Когда я заменил на использование CTime, то стало работать и после этой даты(заменил только для выброса, в остальных местах не менял). Изменено 13 Января 2010 пользователем malandrinus Ссылка на комментарий
dimos 10 Опубликовано 9 Января 2010 Поделиться Опубликовано 9 Января 2010 (изменено) malandrinus, чего-то я это нигде не встречал, а что это вообще такое? cse_alife_item_weapon_auto_shotgun | CWeaponAutomaticShotgun Как-то можно штуцер сделать (один ствол нарезной, второй гладкоствол)? Почему-то через подствольник W_GLAUNC не получается Изменено 13 Января 2010 пользователем malandrinus Цензура ограничивает творчество © by me Ссылка на комментарий
Malandrinus 615 Опубликовано 9 Января 2010 Автор Поделиться Опубликовано 9 Января 2010 (изменено) dimos, Это «Отбойник» - автоматический дробовик из ЗП. Секция wpn_protecta в файле configs\weapons\w_protecta.ltx. Я думаю, что не получится сделать оружие, стреляющее двумя типами патронов. При выстреле из подствольника спавнится граната, обрабатывается её физика и т.д. Это не превратить в выстрел из дробовика. Ну по крайней мере я не знаю, как это сделать. W_GLAUNC - это вообще никак не поможет, поскольку это объект подствольника, а все аддоны - это просто инвентарные предметы. Они не стреляют, стреляют стволы. При надевании аддона сам объект аддона исчезает, а у ствола просто устанавливается соответствующий флажок. Изменено 13 Января 2010 пользователем malandrinus Плагины Total Commander для работы с игровыми архивами: Архиваторный плагин (для работы с одиночным архивом): link1 link2 Системный плагин (для распаковки установленной игры): link1 link2 Ссылка на комментарий
dimos 10 Опубликовано 9 Января 2010 Поделиться Опубликовано 9 Января 2010 (изменено) malandrinus, пардон, все время сужу по ТЧ, а там этого класса нет. Кстати, может как-то сделать небольшой пост по отличиям ЗП от предыдущих частей, хотя бы после выхода АМК ЗП? Или добавить коменты к предыдущим статьям, хотя первую страницу редко кто читает... Например, тот же класс CCar, в ЗП его уже нет. Изменено 13 Января 2010 пользователем malandrinus Цензура ограничивает творчество © by me Ссылка на комментарий
Malandrinus 615 Опубликовано 10 Января 2010 Автор Поделиться Опубликовано 10 Января 2010 (изменено) Например, тот же класс CCar, в ЗП его уже нет. Да есть он там! Кто сказал что нет? Даже в lua_help остался. Можно создать машину, хотя и не получается на ней поездить. Изменено 13 Января 2010 пользователем malandrinus Плагины Total Commander для работы с игровыми архивами: Архиваторный плагин (для работы с одиночным архивом): link1 link2 Системный плагин (для распаковки установленной игры): link1 link2 Ссылка на комментарий
lekzd 1 Опубликовано 10 Января 2010 Поделиться Опубликовано 10 Января 2010 (изменено) Замеченные мной отличия скриптов ЗП от ТЧ (предлагаю развивать тему): Скрытый текст - все операции над текстом теперь вынесены в подкласс TextControl(), который вызывается от класса окна-родителя - отсутствует функция setTextureOffset() - теперь координаты текстуры задаются только через XML - отсутствует функции setColor(), setTextColor(), getColor(), setHeading(), setTextX(), SetHighlightColor(), GetTextY(), GetClipperState(), SetClipperState, SetOriginalRect() - продолжать список можно долго - изменился init() окна, судя по-всему окна теперь инициализируются как-то самостоятельно - вызов окна через ShowDialog(true) - аргументы функций, связанных с размерами и положением окна теперь задаются через vector_set() и Frect_set() - судя по всему скриптер у ПЫСов сунул нос в скрипты иностранных игрушек - почему-то не получается через скрипты запустить нормальную работу CuiListItem - контрол выдает ошибку при работе методами ТЧ Скрытый текст - в bind_stalker появился колбэк на юзание предмета + теперь у любого "съедобного" предмета строка в меню ПКМ называется "использовать" вместо "съесть" и "выпить" как в ТЧ - исправлена ошибка в g.script, из-за которой РГ-6 не считался оружием у НПС, хотя когда я его заспавнил я ужаснулся - стрелять теперь из него можно только метров на 10 и то никто не станет вам врагом, даже если вы будете бить в упор - появилась интересная функция string.find(command_line(), "-key") - вернет true если в команой строке запустить сталкера с ключом "-key" (если запускать игру с ключом "-designer" то функция апдейта bind_stalker перестанет выполняться) Изменено 25 Июля пользователем Kirgudu i-igroman.ru - Мой, принципиально новый сайт о компьютерных играх Ссылка на комментарий
lekzd 1 Опубликовано 12 Января 2010 Поделиться Опубликовано 12 Января 2010 Один из основных скриптов, грузится движком все функции из него считаются глобальными function load_scheme(filename, scheme, stype) загружает схему поведения НПС из файла скрипта подробнее можно поглядеть в modules.scriot function action(obj,...) Задает объекту некоторое действие или несколько действий function round (value) округляет число value до целого также в lua есть глобальная функция math.ceil(value) - округляет число, до нижнего значения т.е. math.ceil(2.9342) = 2 function distance_between(obj1, obj2) возвращает дистанцию между объектами, судя по всему в "метрах" function distance_between_safe(obj1, obj2) аналогична предыдущей функции, НО! не вылетает, если один из объектов = nil function has_alife_info(info_id) Проверка на инфопоршны, даже если игрока не существует info_id - строка, имя инфопоршена function reset_action (npc, script_name) Отменяет выполнение схемы у НПС function GiveInfoViaPda(obj_receiver, obj_sender, info_number) Скидывает на ПДА кому-угодно сообщение от кого-угодно (судя по всему осталось от 1935-го билда, где можно было общаться через ПДА) obj_receiver - npc получатель obj_sender - npc отправитель info_number - айдишник инфопоршена function interrupt_action(npc, script_name) Если в данный момент у НПС выполняется какое-то действие, прерывает его и отключает скриптовый режим function random_choice(...) случайно возвращает одно из введенных значений function new_action(...) так и не понял, что она делает - используется толь в скрипте copy of a1.script function set_current_time (hour, min, sec) Задает игровое время function str_split (str) разбивает строку на 4 части, ориентируясь по разделителю "_" (судя по всему из ранних билдов, ибо сейчас нигде не используется) function random_number (min_value, max_value) Возвращает случайное число в диапазоне от min_value до max_value function day_time() Возвращает время в миллисекундах function local_hours() Возвращает время в часах function parse_names( s ) разбивает строку S на таблицу из имен чего-либо, возвращает таблицу function parse_nums( s ) разбивает строку S на таблицу из чисел, возвращает таблицу function is_object_online(obj_id) Возвращает является ли объект в онлайне function get_clsid(npc) Возвращает id класса объекта function isWeapon(object) Возвращает является ли объект оружием благодаря этой функции НПС просят актора убрать оружие function yaw( v1, v2 ) Возвращает какое-то значение поворота для этих точек function vector_rotate_y (v, angle) Вращает вектор вокруг оси y против часовой стрелки возвращает вектор function clear_table (t) Функция очищает таблицу t function stop_play_sound(obj) прерывает звук от объекта function object_type(obj) возвращает строку-название типа объекта , например "stalker" "monster" function is_object_monster(obj) Возвращает является ли оbj монстром function switch_online (id) function switch_offline (npc) переводят объект в оффдайн и онлайн function get_actor_id() Возвращает id актора function IsMonster (object, class_id) Возвращает является ли объект монстром function IsStalker (object, class_id) Возвращает является ли объект сталкером (актору тоже выдает true) function level_object_by_sid( sid ) Возвращает объект по его story_id function id_by_sid( sid ) возвращает id объекта по его story_id function set_postprocess(name_ini_file) function remove_postprocess() задает/снимает постпроцесс имя файла указывается с расширением .PPE function set_inactivate_input_time(delta) отключает управление актором на время delta в секундах function set_sleep_relocate(point, look, timeout) Задает актору позицию положения, позицию куда смотреть, время сна в минутах. Это все в силе, если раскомментировать часть функции function odd( x ) Проверяет целую часть числа x на нечётность function on_actor_critical_power() function on_actor_critical_max_power() function on_actor_bleeding() function on_actor_satiety() function on_actor_radiation() function on_actor_weapon_jammed() function on_actor_cant_walk_weight() function on_actor_psy() Функции, которые выполняются при кровотечении, истощении, голоде и т.п. - редактируются тольок в самом _g.script function set_actor_rank(rank) задает актору кол-во очков опыта, равное rank ("novice" "stalker" "veteran" "master") function get_texture_info(id_name, id_default) Возвращает имя файла текстуры по ее id Также возвращает x2 - ширину текстуры y2 - высоту тестуры Часть функций была опущена из-за того, что они являются служебными для объектов, описанных в _g.script i-igroman.ru - Мой, принципиально новый сайт о компьютерных играх Ссылка на комментарий
Vano_Santuri 33 Опубликовано 17 Января 2010 Поделиться Опубликовано 17 Января 2010 Вот такой вопрос, если ответите, то буду очень признателен: 1)Есть функция нет-пакета для спавна аномалий, за авторством Шокера, делалась для ЧН, подходит ли для ЗП? Если нет , что поправить? function create_anomalies(section,rad_anom,x,y,z,lv,gv,mode) if gv==nil then gv=db.actor:game_vertex_id() end if lv==nil then lv=db.actor:level_vertex_id() end if pos==nil then pos=db.actor:position() end local p_obj = alife():create(section,vector():set(x,y,z),lv,gv) local packet = net_packet() packet:w_begin(0) p_obj:STATE_Write(packet) packet:r_seek(2) local game_vertex_id = packet:r_u16() local cse_alife_object__unk1_f32 = packet:r_float() local cse_alife_object__unk2_u32 = packet:r_s32() local level_vertex_id = packet:r_s32() local object_flags = packet:r_s32() local custom_data = packet:r_stringZ() local story_id = packet:r_s32() local cse_alife_object__unk3_u32 = packet:r_s32() local shape_count = packet:r_u8() for i=1,shape_count do local shape_type = packet:r_u8() if shape_type == 0 then local center = packet:r_vec3() local radius = packet:r_float() else local box = packet:r_matrix() end end local restrictor_type = packet:r_u8() local cse_alife_custom_zone__unk1_f32 = packet:r_float() local cse_alife_custom_zone__unk2_u32 = packet:r_s32() local on_off_mode_enabled_time = packet:r_s32() local on_off_mode_disabled_time = packet:r_s32() local on_off_mode_shift_time = packet:r_s32() local offline_interactive_radius = packet:r_float() local artefact_spawn_places_count = packet:r_u16() local cse_alife_anomalous_zone__unk1_u32 = packet:r_s32() local last_spawn_time_present = packet:r_u8() packet:w_u16(game_vertex_id) packet:w_float(cse_alife_object__unk1_f32) packet:w_s32(cse_alife_object__unk2_u32) packet:w_s32(level_vertex_id) packet:w_s32(object_flags) if mode~=nil then custom_data = mode end packet:w_stringZ(custom_data) packet:w_s32(story_id) packet:w_s32(cse_alife_object__unk3_u32) packet:w_u8(1) packet:w_u8(0) local sphere_center = vector() sphere_center:set(0, 0, 0) packet:w_vec3(sphere_center) radius = rad_anom packet:w_float(radius) packet:w_u8(restrictor_type) packet:w_float(cse_alife_custom_zone__unk1_f32) cse_alife_custom_zone__unk2_u32 = bit_not(0) packet:w_s32(cse_alife_custom_zone__unk2_u32) packet:w_s32(on_off_mode_enabled_time) packet:w_s32(on_off_mode_disabled_time) packet:w_s32(on_off_mode_shift_time) packet:w_float(offline_interactive_radius) packet:w_u16(artefact_spawn_places_count) packet:w_s32(cse_alife_anomalous_zone__unk1_u32) if mode == nil then packet:w_u8(last_spawn_time_present) end p_obj:STATE_Read(packet, packet:w_tell()-packet:r_tell()) return p_obj end 2)Что такое стэки(стеки)? 3)Что такое перпелолнение стэков(стеков)? 4)К чему приводит переполнение стэков(стеков)? Вылеты без логов могут быть вызваны переполнением стэков(стеков)? 5)Если я заспавним аномалию через нет-пакет, могу ли я удалить ее этой функцией? function remove_anom(obj) if obj~=nil then alife():release(alife():object(obj:id()), true) return true end return false end вернее, это будет нормальное удаление? или оно может быть с ошибками? Есть ли специальная функция, удаляющая объекты, заспавненные нет-пакетом? 6)Довольно простой пример, заспавнил 100 аномалий, удалил их все, потом опять заспавнил, и так н-ое количество раз, в итоге, при подходе к какой нить области(аномалии) происходит вылет без лога(стар трэк), вопрос в следующем, почему так? Что-то кончается, что-то начинается... Ссылка на комментарий
Monnoroch 6 Опубликовано 17 Января 2010 Поделиться Опубликовано 17 Января 2010 (изменено) 1) врятли чтото изменилось... 2) ну я не могу сказать по научному,но это чтото типа выделенной памяти для некоего списка. 3) приводит к тому,что данное записывается в него а там нет места - ну и вылет. 4) врятли.есть вылеты stack overflow 5) а почему нет?можно. === в качестве коммента заспавненные нет-пакетом Это что за бред? Спавнишь методом alife():create() А потом переписываешь пакет есму с помощью обьекта класса net_packet() 6)попробуй заспавнил,удалил,сэйв,лоад,заспавнил,удалил.... и т.п. Никогда не вылетишь Изменено 17 Января 2010 пользователем Monnoroch Ссылка на комментарий
Vano_Santuri 33 Опубликовано 17 Января 2010 Поделиться Опубликовано 17 Января 2010 (изменено) Monnoroch, Все, решил свою проблему, вылет был из-за того, я так полагаю, что слишком много действий в один момент. Сделал по умному, разбил эти 100 аномалий на 10 циклов, и поставил на таймер, теперь через каждые 2 минуты спавнится цикл аномалий из 10 штук. класно Даже не зависает ни на капельку. Немнго инфы для людей, возможно к лассам она не имеет никакого значения, но вот : 1)Допустим вы хотите заспавнить предмет\монстра \непися или еще чего в случайно рандомном месте , но не знаете как.Вот пример простой функции: function random_place_spawn() lv_new = math.random(1845795) -- ( количество левелвертесов на уровне, или иное значение, если надо сузить область) pos_new = level.vertex_position(lv_new) --(этот метод находит вершины вертекса) alife():create("cекция объекта",vector():set(pos_new.x,pos_new.y,pos_new.z),lv_new,0) end 0 - это геймвертекс затона, т.е общий, но работает для всех точек. 317 - Юпитер 666 - Припять Изменено 15 Декабря 2017 пользователем Murarius 1 Что-то кончается, что-то начинается... Ссылка на комментарий
Malandrinus 615 Опубликовано 17 Января 2010 Автор Поделиться Опубликовано 17 Января 2010 1)Есть функция нет-пакета для спавна аномалий, за авторством Шокера, делалась для ЧН, подходит ли для ЗП? Если нет , что поправить?Проще всего попробовать. Если же хочется разобраться в сути, то надо взять acdc для ЗП и посмотреть там формат нетпакета и сравнить его с форматом для ЧН. 2)Что такое стэки(стеки)? =) Стек вообще означает "стопка чего-либо". Классическая иллюстрация этого понятия - это устройство в барной стойке, куда складывают мытые тарелки. В этом случае стопка подпружинена снизу и ограничена сверху, чтобы верхняя тарелка всегда была строго в одной позиции. Смысл стека в любом его понимании - это хранилище объектов, из которых всегда доступен только последний, помещённый туда: "последний зашёл - первый вышел", "Last In - First Out", LIFO. В компьютерах, в силу фундаментальности такого принципа организации данных, стеки используются повсеместно и часто поддерживаются на уровне команд процессора. В частности, на стеке основан механизм вызова функций: адрес возврата перед вызовом пишется в стек, это позволяет после завершения работы функции вернуться в точку вызова. В стек же пишутся и аргументы функции (не всегда). У Lua свой стек, не связанный со стеком процессора (точнее потоков). Написание этого слова через "Э" или через "Е" в целом достаточно произвольно и зависит от доминирующей нормы произношения =) Москвичи больше "э"кают, питерцы чаше предпочитают более мягкие варианты с "е". Впрочем, это уже могли и законодательно устаканить. 3)Что такое перпелолнение стэков(стеков)?Под стек заранее выделяется память. Он заполняется в одном направлении. Когда выделенная область заканчивается - это переполнение стека. 4)К чему приводит переполнение стэков(стеков)? Вылеты без логов могут быть вызваны переполнением стэков(стеков)?Они же без логов. Как узнаешь, могут или нет =) Вылет без лога может быть при переполнении стека процессора, но это - довольно редкая ситуация в работающем и отлаженном приложении. Переполнение стека Lua - вылет может быть запросто, но обычно в этой ситуации есть лог. 6)Довольно простой пример, заспавнил 100 аномалийПричина вылетов может быть разная. Движок игры исходно не рассчитывался на все те безобразия, что вытворяют с ним модостроители. Может и нельзя 100 аномалий спавнить, может нельзя делать это слишком часто, а возможно, где-то в скрипте просто баг. Для начала, стоит попробовать поэкспериментировать. А если не 100, а 50 аномалий? Тоже вылет? Плагины Total Commander для работы с игровыми архивами: Архиваторный плагин (для работы с одиночным архивом): link1 link2 Системный плагин (для распаковки установленной игры): link1 link2 Ссылка на комментарий
Рекомендуемые сообщения
Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий
Комментарии могут оставлять только зарегистрированные пользователи
Создать аккаунт
Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!
Зарегистрировать новый аккаунтВойти
Есть аккаунт? Войти.
Войти