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

Справочник по функциям и классам


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

Сначала в двух словах, как пользоваться механизмом выдачи заданий.
Для выдачи задания есть метод класса game_object (естественно, это должен быть актор)

void give_task(
    CGameTask* <задание>, -- подготовленный объект задания, см. далее
    int <время до истечения>, -- время от начального момента до истечения срока задания в ms
    boolean <проверять на наличие такого>) -- если true и задание с таким идентификатором уже есть, то не будет добавлено

Комментарии:


1. Нетрудно посчитать, что в 32-х разрядное целое влазит миллисекунд примерно на месяц. Соответственно - это и будет максимально возможным временем для задания.
2. Третий параметр вероятно имеет смысл использовать для разных категорий заданий. Одноразовые квестовые должны иметь параметр true, а повторяющиеся однотипные - false

Выдаём задания так:
1. Сначала надо подготовить объект типа CGameTask. Самый простой способ - воспользоваться уже готовыми заданиями, описанными в xml файлах. Для этого у класса CGameTask есть метод load
local 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. На мой взгляд всё стало проще, и если Вы поняли, как это работает в ТЧ, то экстраполировать это на ЧН и ЗП труда не составит.

Изменено пользователем Kirgudu
  • Спасибо 1
  • Полезно 1
 

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

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

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

 

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

А кто-нибудь знает как определить, что актор бежит?

 

пока нашел способ определения по значению accuracy() но приходится подгонять его под каждое оружие

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

i-igroman.ru - Мой, принципиально новый сайт о компьютерных играх

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

lekzd,

можно попытаться по разнице между position и center. Это типа по наклону туловища =) Но там тоже нестабильные значения.

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

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

 

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

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

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

 

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

malandrinus, я сделал полностью динамический ХУД и скрываю его во время бега

при резких скачках он начинает "моргать" (значения резко скачут), что приводит к падению ФПС

 

можешь привести код проверки по трем точкам? (я делал код проверки по x z + усреднение значений по двум точкам во времени)

i-igroman.ru - Мой, принципиально новый сайт о компьютерных играх

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

Введение

Скрытый текст

При первом взгляде на 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.scriptse_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_abstract
class cse_temporary : cse_abstract
class 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_restrictor
class 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_skeleton
class 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

 

 

 

 

 

Изменено пользователем Kirgudu
 

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

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

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

 

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

Полагаю, красивая картинка никому не помешает. Вот вам диаграмма серверных классов с высоты птичьего полёта =) Обращаю внимание на нотацию записи: большая пустая стрелка означает отношение обобщения (или наследования иными словами) и направлена от унаследованного класса к базовому. Включение абстрактного интерфейса обозначается стрелкой с кружочком и указанием, какой интерфейс наследуется. Это сокращённая форма записи, позволяющая избавиться от нагромождения линий и лучше понять основную линию наследования.

1b2c4918.png

 

С серверными классами пока всё. Некоторые выводы по данному этапу.

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

2. Между ТЧ, ЧН и ЗП не так уж и много отличий. Хотя отличия имеются: добавлено несколько новых классов, изрядно добавлено новых методов в существующих классах и пара методов исчезла.

3. Я не описывал ни назначение классов, ни назначение их методов. В некоторых местах (в основном для новых методов в ЧН и ЗП) не удалось пока получить информации о параметрах и возвращаемых значениях. Наверняка где-то упустил продокументировать различие между играми.

 

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

 

Продолжение следует...

Изменено пользователем malandrinus
 

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

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

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

 

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

Просто наблюдение:

Разница между значениями game.time() и game.get_game_time()" - заметил, что при старте новых игр она каждый раз разная, и где-то, после 40млн.милисекунд, при рестарте счётчика, её значение изменяется...

 

как ты высчитываешь разницу?
Стартовал новую игру, получал game.time() и game.get_game_time(), переводил game.get_game_time() в мсек, вычитал и смотрел разницу.

И какой рестарт счётчика ты имеешь в виду? Тот, что раз в месяц?
Разница, была статична до того как, через какое-то игровое время, значение game.time() сбросилось и продолжило счёт с нуля, разница то-же пересчиталась и стала другой. Вот насчёт 40 млн... это я визуально запомнил - это может и не так быть, но срок был, в роде больше месяца, намного.

 

Надо повторить эксперимент, а то вдруг чего не так делал... перепроверю.

Но то, что game.time() обнулялась - это точно.

Изменено пользователем 7.9

всё легко

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

7.9,

всё верно, только не 40 млн., а 4 мрд., точнее максимальное 32-х разрядное беззнаковое целое:

4294967295 что в миллисекундах составляет примерно 1193 часа, т.е. 49 дней.

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

Изменено пользователем malandrinus
 

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

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

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

 

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

Разбираем систему клиентских классов.

Сначала немного лирики.

Скрытый текст

Итак, на клиентской стороне есть своя иерархия классов, отвечающих за онлайновые (т.е. клиентские) объекты. Все они унаследованы от CGameObject. Дерево наследования там не столь сложное, как для серверных классов. Тем не менее для каждого (почти) типа игровых объектов есть свой класс, и при первом взгляде всё смотрится вполне прилично. Но это только на первый взгляд. При более внимательном рассмотрении выясняется, что классы хоть и есть, но добраться до произвольного клиентского объекта невозможно. Т.е. нет никаких функций, с помощью которых можно было бы получить произвольный клиентский объект, производный от CGameObject. Соответственно, нет и возможности вызывать их методы. Кроме того, эти классы не предназначены для создания на их основе скриптовых классов. Таким образом, все общие пути для использования объектов этого класса закрыты. Соответственно, основным и почти единственным интерфейсом к объектам на клиентской стороне остаётся game_object
Однако не всё так трагично =) Есть исключения. Если в классе добавлены какие-либо методы сверх основного набора из CGameObject, то для получения объектов такого класса в game_object имеются специальные методы. В ТЧ исходно всего три таких класса: CCarCHelicopter и hanging_lamp. Соответственно в game_object есть методы:
get_car() - для CCar
get_helicopter() - для CHelicopter
get_hanging_lamp() - для hanging_lamp
В ЧН методы добавлены в классы CPhysicObjectCArtefactCZoneCampfire и CAI_Bloodsucker. Соответственно появились и новые методы в game_objectget_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.
ICollidable
IRenderable
ISheduled
Непосредственно от DLL_Pure наследованы всего три класса.
class ce_smart_zone : DLL_Pure
class 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_Stalker
CAI_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

//устройства
CTorch
CSimpleDetector -- класс есть, но не документирован в lua_help
CAdvancedDetector -- класс есть, но не документирован в lua_help
CEliteDetector -- класс есть, но не документирован в lua_help
CScientificDetector -- класс есть, но не документирован в 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
CWeaponAmmo

CInventoryBox
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

//Шкурки
CStalkerOutfit
CHelmet -- класс есть, но не документирован в lua_help

Артефакты

Скрытый текст


class CArtefact : CGameObject {
    function SwitchVisibility(boolean);
    function FollowByPath(string, number, vector);
    function GetAfRank() const;
};

Производные от CArtefact
CBastArtefact
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 -- не экспортированный класс
-- серверный также не экспортирован    |

 

Изменено пользователем Murarius
 

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

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

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

 

Ссылка на комментарий
Вот этот залипон со счётчиком времени - это совершенно типичный пример. И ведь игра заведомо создавалась, как шутер с элементами РПГ. Т.е. подразумевалось, что игрок будет исследовать локации, возвращаться на них, чтобы доделать квесты и прочее в этом роде. Учитывая дефолтовое соотношение игрового времени к реальному десять (!) 49 дней с легкостью превращаются всего в 5 дней реального игрового времени. Пять дней?! Для РПГ?! Смешно даже. И что мешало разрабам просто взять и посчитать, на сколько хватит этого счётчика?

В движке в классе CTime 64х-разрядный счетчик и считает он нормально. Вообще вокруг этой проблемы слишком много шума. В оригинальной игре я ее не встречал. Видел только в АМК моде, но там использовали функцию level.get_time_days(), которая возвращает день месяца. Отсюда и пошла проблема 1 июня. Когда я заменил на использование CTime, то стало работать и после этой даты(заменил только для выброса, в остальных местах не менял).

 

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

malandrinus, чего-то я это нигде не встречал, а что это вообще такое?

cse_alife_item_weapon_auto_shotgun     |  CWeaponAutomaticShotgun

Как-то можно штуцер сделать (один ствол нарезной, второй гладкоствол)? Почему-то через подствольник W_GLAUNC не получается :(

 

Изменено пользователем malandrinus
Цензура ограничивает творчество © by me
Ссылка на комментарий

dimos,

Это «Отбойник» - автоматический дробовик из ЗП. Секция wpn_protecta в файле configs\weapons\w_protecta.ltx.

Я думаю, что не получится сделать оружие, стреляющее двумя типами патронов. При выстреле из подствольника спавнится граната, обрабатывается её физика и т.д. Это не превратить в выстрел из дробовика. Ну по крайней мере я не знаю, как это сделать.

W_GLAUNC - это вообще никак не поможет, поскольку это объект подствольника, а все аддоны - это просто инвентарные предметы. Они не стреляют, стреляют стволы. При надевании аддона сам объект аддона исчезает, а у ствола просто устанавливается соответствующий флажок.

Изменено пользователем malandrinus
 

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

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

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

 

Ссылка на комментарий
malandrinus, пардон, все время сужу по ТЧ, а там этого класса нет. Кстати, может как-то сделать небольшой пост по отличиям ЗП от предыдущих частей, хотя бы после выхода АМК ЗП? :) Или добавить коменты к предыдущим статьям, хотя первую страницу редко кто читает... Например, тот же класс CCar, в ЗП его уже нет. Изменено пользователем malandrinus
Цензура ограничивает творчество © by me
Ссылка на комментарий
Например, тот же класс CCar, в ЗП его уже нет.
Да есть он там! Кто сказал что нет? Даже в lua_help остался. Можно создать машину, хотя и не получается на ней поездить. Изменено пользователем malandrinus
 

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

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

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

 

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

Замеченные мной отличия скриптов ЗП от ТЧ (предлагаю развивать тему):

Скрытый текст

- все операции над текстом теперь вынесены в подкласс 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 и то никто не станет вам врагом, даже если вы будете бить в упор :lol:

- появилась интересная функция string.find(command_line(), "-key") - вернет true если в команой строке запустить сталкера с ключом "-key" (если запускать игру с ключом "-designer" то функция апдейта bind_stalker перестанет выполняться)

 

Изменено пользователем Kirgudu

i-igroman.ru - Мой, принципиально новый сайт о компьютерных играх

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

Один из основных скриптов, грузится движком

все функции из него считаются глобальными

 

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 - Мой, принципиально новый сайт о компьютерных играх

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

Вот такой вопрос, если ответите, то буду очень признателен:

 

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 аномалий, удалил их все, потом опять заспавнил, и так н-ое количество раз, в итоге, при подходе к какой нить области(аномалии) происходит вылет без лога(стар трэк), вопрос в следующем, почему так?

 

 

Что-то кончается, что-то начинается...

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

1) врятли чтото изменилось...

2) ну я не могу сказать по научному,но это чтото типа выделенной памяти для некоего списка.

3) приводит к тому,что данное записывается в него а там нет места - ну и вылет.

4) врятли.есть вылеты stack overflow

5) а почему нет?можно.

 

===

 

в качестве коммента

заспавненные нет-пакетом

Это что за бред?

Спавнишь методом alife():create()

А потом переписываешь пакет есму с помощью обьекта класса net_packet()

 

6)попробуй заспавнил,удалил,сэйв,лоад,заспавнил,удалил.... и т.п.

Никогда не вылетишь :)

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

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 - Припять

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

Что-то кончается, что-то начинается...

Ссылка на комментарий
1)Есть функция нет-пакета для спавна аномалий, за авторством Шокера, делалась для ЧН, подходит ли для ЗП? Если нет , что поправить?
Проще всего попробовать. Если же хочется разобраться в сути, то надо взять acdc для ЗП и посмотреть там формат нетпакета и сравнить его с форматом для ЧН.

2)Что такое стэки(стеки)?
=) Стек вообще означает "стопка чего-либо". Классическая иллюстрация этого понятия - это устройство в барной стойке, куда складывают мытые тарелки. В этом случае стопка подпружинена снизу и ограничена сверху, чтобы верхняя тарелка всегда была строго в одной позиции. Смысл стека в любом его понимании - это хранилище объектов, из которых всегда доступен только последний, помещённый туда: "последний зашёл - первый вышел", "Last In - First Out", LIFO. В компьютерах, в силу фундаментальности такого принципа организации данных, стеки используются повсеместно и часто поддерживаются на уровне команд процессора. В частности, на стеке основан механизм вызова функций: адрес возврата перед вызовом пишется в стек, это позволяет после завершения работы функции вернуться в точку вызова. В стек же пишутся и аргументы функции (не всегда). У Lua свой стек, не связанный со стеком процессора (точнее потоков).

Написание этого слова через "Э" или через "Е" в целом достаточно произвольно и зависит от доминирующей нормы произношения =) Москвичи больше "э"кают, питерцы чаше предпочитают более мягкие варианты с "е". Впрочем, это уже могли и законодательно устаканить.

3)Что такое перпелолнение стэков(стеков)?
Под стек заранее выделяется память. Он заполняется в одном направлении. Когда выделенная область заканчивается - это переполнение стека.

4)К чему приводит переполнение стэков(стеков)? Вылеты без логов могут быть вызваны переполнением стэков(стеков)?
Они же без логов. Как узнаешь, могут или нет =) Вылет без лога может быть при переполнении стека процессора, но это - довольно редкая ситуация в работающем и отлаженном приложении. Переполнение стека Lua - вылет может быть запросто, но обычно в этой ситуации есть лог.

6)Довольно простой пример, заспавнил 100 аномалий
Причина вылетов может быть разная. Движок игры исходно не рассчитывался на все те безобразия, что вытворяют с ним модостроители. Может и нельзя 100 аномалий спавнить, может нельзя делать это слишком часто, а возможно, где-то в скрипте просто баг.

Для начала, стоит попробовать поэкспериментировать. А если не 100, а 50 аномалий? Тоже вылет?

 

 

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

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

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

 

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

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

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

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

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

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

Войти

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

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

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

×
×
  • Создать...