Artos 99 Опубликовано 16 Октября 2011 (изменено) *Shoker* Да, упоминания про 'updskeleton_flags' нужно просто удалить из кодов. Если есть желание можешь потестить новую версию: m_net_utils_111015- изменен формат получаемой таблицы нет-пакета. Параметры UPDATE выделены в субтаблицу 'Table.upd' - изменена последовательность аргументов при вызове записи пакета: 'Table,soObj,Flag' -> 'soObj,Table'. Необходимость записи UPDATE_write определяется по наличию субтаблицы 'Table.upd'. - введены общие функции: Get_NetPacket/Set_NetPacket, самостоятельно определяющие класс серверного объекта и выбирающие соотв.методы чтения/записи. Т.о. чтение/запись возможны через единые общие методы, которым в качестве первого аргумента передается серверный объект, а вторым при чтении - флаг чтения полного пакета, а при записи - таблица для записи пакета. Изменено 16 Октября 2011 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Поделиться этим сообщением Ссылка на сообщение
Artos 99 Опубликовано 19 Октября 2011 (изменено) Scarabay Нож для НПС не юзаем. Хочешь сделать - приаттачивай к его руке и махай 'анимацией'. В общем смотри схемы 'мордобоя' из модов и делай по аналогии. Поправлю немного Desertir'а, нет никакой надобности добавлять 'лишний' аргумент (self) в коллбэк актору. И так понятно, что юзает (who) именно он, а не кто иной. Также несколько странная фраза: Desertir: А вот "проверять, существует ли предмет, который потерян" вообще интересен Если тому же 'батону' в конфиге прописать 'многопорционность', то для таких 'многократных' использований как раз проверка 'съеден' ли батон иль только 'надкушен' (в процессе поедания) - совсем не лишне! Следует все же различать то, о чем говорит событие, а не додумывать его иль ориентироваться только на общие случаи. Правильным для 'отследить поедание' (см. вопрос) - достаточен коллбэк 'use_object', а вот для однозначности 'съеден' - тут уже без доп. проверки на исчезновение предмета из игры не обойтись. Изменено 19 Октября 2011 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Поделиться этим сообщением Ссылка на сообщение
Artos 99 Опубликовано 22 Октября 2011 (изменено) *Shoker* И чего тебе непонятно в логах? 'self.sid' - рандомная метка для локальной идентификации объектов в лог-строках. Сделано по дурному ... при каждой перезагрезке игры этот индекс изменяется, так что ориентироваться можно только в текущей сессии. Зачем вообще вызываются методы STATE_Read()/STATE_Write() ? Ответ вроде как очевиден. В игре имеются серверные объекты и клиентские. Клиентские - порождение серверных. В игре (для многих объектов постоянно) идет обмен между серверными и клиентскими объетами. В конце игры - в серверные объекты сохраняется то, что необходимо от клиентских ... То, что в зарузке используется метод STATE_Write() как раз и не должно вызывать вопроса, если учесть 'зеркальность' названий. Методы STATE(UPDATE)_Write(Read) применяются к объектам, точнее они и есть методы объектов(!), и учитывая что записть типа: se_object:STATE_Write(packet) - можно прочитать как "запись в нет-пакет параметров серверного объекта" и далее этот пакет с данными можно читать и использовать в игре, то ясно - это по сути операция ЧТЕНИЯ данныех объекта, для чего и получается пакет данным методом. Учитывая вышесказанное, при загрузке требуется прочитать серверные данные объектов, для чего они должны вначале быть записаны в некий нет-пакет, из которого и могут быть далее прочитаны. Так что запоминай и привыкай к 'зеркальной' трактовке: Чтобы прочитать параметры - требуется вначале их из объекта записать в нет-паекет. Чтобы внести изменения (и записать) - требуется, чтоб (ис)правленый нет-пакет был прочитан объектом. Добавлено через 91 мин.: P.S. Кстати, можешь опробовать обновленный вариант модуля работы с нет-пакетами:[spoiler="читалка/писалка" (дозаполнил)]m_net_utils_111022 Основное отличие: выбор метода чтение/записи нет-пакета производится автоматически по переданному в качестве аргумента серверному объекту. Определяется его класс и по таблице из конфиг-файла выбирается соответствующий метод (если имеется). Установка - скопировать скрипт в папку скриптов, конфиг - в папку конфигов. Вызовы: чтение - Get_NetPacket(se_obj [,flag_upd]) , запись - Set_NetPacket(se_obj, table) Изменено 23 Октября 2011 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Поделиться этим сообщением Ссылка на сообщение
Artos 99 Опубликовано 24 Октября 2011 (изменено) *Shoker* Странноватые вопросы возникают у тебя ... (по STATE_Read/Write). Вроде как даже пояснил ... Как вообще возникают объекты в игре? Как они получают свои параметры? Как меняют свои параметры? Это обшие вопросы и не имеют к теме отношения. Но все же поясню. При старте игры из сэйва читаеся информация о всех динамических объектах, которые были в игре при сохранении. Для новой игры (НИ) информация о таких объектах берется из all.spawn'а. Сервер создает объекты-заготовки соответствующего класса для всех объектов. На этом этапе это просто шаблоны с дефолтными параметрами и с единыи ID-65535 (т.е. игровой идентификатор пока не задан!). Далее, в объекты-заготовки считываются (STATE_Read) их конкретные параметры и объекты расставляются по локациям, координатам и пр ... После этого, полученные объекты считываются (STATE_Write) запущенным сервером, чтобы прочитать их параметры и определить какие объекты относятся к текущей локации. Для объектов, которые биндятся и могут иметь сохраненные в сэйве параметры в pstor'ах - вновь запускается читалка (STATE_Read) и считываются эти параметры. Естественно, после того, как сервер считал текущие параметры объектов на локации - вновь необходимо дать информацию по этим объектам в игру, т.е. клиентские объекты должны иметь текущий нет-пакет (STATE_Write). Ну и т.д. ... Например для объекта 'оружие в рукаг ГГ' будет вызываться STATE_Read/Write периодически, что можно даже с некоторой погрешностью испорльзовать для счтывания текущего кол-ва патронов для этого объекта ... не задействуя сторонние апдейтеры. Ну а модуль нет-пакетов не переопачивается каждый раз. Суть (на 95%) остается прежней. Изменено 24 Октября 2011 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Поделиться этим сообщением Ссылка на сообщение
Artos 99 Опубликовано 25 Октября 2011 (изменено) *Shoker* Скорость/ресурсоемкость в первую очередь определяется алгоритмом! Выбор конкретных функций и соответственно их суммарная скорость - производная от алгоритма. 1. Учись задавать вопросы так, чтлбы было желание ответить. На вопрос типа: "Кто знает, почему в Сталкере разработчики ..." - кроме как ответа: "Поди к ним и спроси!", мне, например, давать не хочется ... А вот вопрос: "В чем отличия/преимущества одного метода по сравнению с другим(и)" - и смыслом наполнен и задуматься заставляет и поделиться мнением/навыком побуждает! 2. Ты не задумывался над тем, что расстояние может быть и отрицательным? Конечно оказаться внутри сталкера/монстра/предмета ГГ не может, но внутри рестриктора, аномалии и т.п. - запросто! Вычисление расстояния до некоей зоны и сравнение с аналогичными - имеет смысл в связке с радиусом зоны до центра которой (иль до периметра) измеряешь. Есть еще и 2D-расстояние (distance_to_xz) - это чтобы и с высотою не промахнуться, ежели например, кто-то 'на 2-ой этаж забрался' ... 3. Ну а ускорять ... есть правило - если слишком много параметров/данных, то следует по-возможности отбросить те, которые в данной ситуации (в данное время) не обязательно учитывать или ими можно пренебречь. Не знаю, что там у тебя с ГГ и аномалиями, но то, что ГГ может за некий период (напримет 15 сек) отбежать на некую лимитированную его возможностями дистанцию, дает возможность периодические (15 сек, а не 20 мсек!) делать выборки из общей таблицы и работать только с 'доступными' объектами/аномалиями. (Пример в известном тебе моде при обходе аномалий неписями ...). Т.о. вернулись в начало: оптимальный алгоритм всегда выигрывает ... Изменено 25 Октября 2011 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Поделиться этим сообщением Ссылка на сообщение
Artos 99 Опубликовано 25 Октября 2011 (изменено) Dennis_Chikin Заглянув в тему "Справочник по функциям и классам" (иль в lua_help.script) - можно увидеть, что работает с гейм-объектами. Если у тебя не работает - ищи причину у себя в неправильном применении метода. Работоспособность метода не только для ГГ - подтверждают и оригинальная игра и моды ... Изменено 25 Октября 2011 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Поделиться этим сообщением Ссылка на сообщение
Artos 99 Опубликовано 26 Октября 2011 Все же стОит для простых смертных дать попроще пояснение, а то и запутаться могут: 1. Метод 'set_relation' применим к гейм-объектам гуманоидов (сталкеры/торговцы) и монстров. 2. Метод устанавливает одно из трех типов 'отношений': друг/нейтрал/враг. 3. Применение: а) oNPC1:set_relation(game_object.friend, oNPC2) или oNPC1:set_relation(0, oNPC2) - сделать NPC2 другом NPC1 б) oNPC1:set_relation(game_object.neutral, oNPC2) или oNPC1:set_relation(1, oNPC2) - сделать NPC2 нейтралом NPC1 в) oNPC1:set_relation(game_object.enemy, oNPC2) или oNPC1:set_relation(2, oNPC2) - сделать NPC2 врагом NPC1 Ну а расчеты от чего зависят и чему равны конкретные численные значения goodwill'ов - это уже тема иная ... "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Поделиться этим сообщением Ссылка на сообщение
Artos 99 Опубликовано 26 Октября 2011 (изменено) Возможность изменить 'direction' при помощи нет пакетов как раз есть, но .... не с помощью общего модуля ' m_net_utils'. Этот параметр находится в секции 'cse_abstract' нет=пакета и доступен только в методах STATE_Write|Read для конкретных классов объектов. Для изменения требуется навык начальной 'перепаковки' нет-пакета (аналогично перепаковкам аномалий/ламп). В 'se_item.script' имеется класс "se_item". Добавив в него соответствующие методы ты сможешь получить доступ к 'packet' с секцией 'cse_abstract' объекта. Ну а далее - дело техники ... А вообще для физ объектов стОит вспомнить наличие 'ph_shell' и 'apply_force', дабы не хитовать, а прикладывать усилия в соотв.направлениях. Добавлено через 4 мин.: Dennis_Chikin 1. Если ты (или кто-то ...) считаете такую строку кода валидной: second_speaker:set_relation(1--[[first_speaker:relation(obj)]], obj) - то вопросы о нерабочести такого кода стОит задавать себе, а не в топиках. 2. СтОит все же различать отдачу команды и результат ее выполнения! Дав команду на изменение отношения одного к другому - как минимум требуется дождаться следующего апдейта (этого объекта) и только тогда проверять: изменилось ли отношение ... Это также как и со здоровьем (health) и аналогичными параметрами - изменяем, а результат только позже проявляется. Изменено 26 Октября 2011 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Поделиться этим сообщением Ссылка на сообщение
Artos 99 Опубликовано 26 Октября 2011 (изменено) malandrinus 1. В данном конкретном случае нет ошибки и парсер игры не увидит ошибки в синтаксисе, но(!) это именно частный случай и не применим во многих других. Блочный комментарий внутри вызова метода валиден, внутри просто функции - ошибочен. Привычка использовать подобное - верный путь к набиванию шишек ... (ИМХО) 2. Когда возникает сомнение в корректности кода - стОит писать код 'классическим' способом, т.е. и без сокращений и тем более без сомнительных комментариев. Строка: second_speaker:set_relation(game_object.neutral, obj) - и ни чем по результату не отличима от исходной и при любом раскладе похволяет отсечь любые нюансы как парсера движка, так и прочее ... И чуть дополню/поправлю вышесказанное: Поля из cse_abstract доступны в STATE_Write только в момент создания объекта1. 'Только' - для немалого числа классов тут излишне. Немало обьектов периодически перезаписывают свои нет-пакеты в процессе игры и при этом можно получить доступ к секции 'cse_abstract', распарсив нет-пакет. Так что тут не все так однозначно и требует индивидуального подхода. А вот менять параметры 'на лету', т.е. для объекта в онлайне - порой чревато ... и требует специальных мер (если они вообще доступны). 2. Пытаться изменять параметры в секции 'cse_abstract' следует в методе 'STATE_Read', т.к. именно при этом серверный объект считывает измененные параметры. Но после этого клиентский объект должен как минимум синхронизироваться с серверным, т.к. должен быть хотя бы один раз метод 'STATE_Write' для объекта. Изменено 26 Октября 2011 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Поделиться этим сообщением Ссылка на сообщение
Artos 99 Опубликовано 26 Октября 2011 (изменено) Dennis_Chikin А почему ты считаешь, что изменив один параметр, и игнорируя наличие иных, ты достигнешь желаемого рузультата? Не стоит забывать, что в игре многое и взаимосвязано и взаимозависимо. Помимо взаимоотношений персоналий на них распространяются и общегрупповые правила и правила гулагов и прочее. Смотреть нужно в конкретной ситуации все взаимозависимые параметры и при необходимости менять и их. А при необходимости даже и денжеры сбрасывать ... Не стоит думать, что игра все сама за модмейкера разрулит. Приводи конкретную ситуацию (желательно применимо к исходной игре) и бум посмотреть ... Не рабочий метод и отсутствие результата после применения метода - далеко не одно и то же. Изменено 26 Октября 2011 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Поделиться этим сообщением Ссылка на сообщение
Artos 99 Опубликовано 26 Октября 2011 (изменено) malandrinus Немного ранее, *Shoker*'у мимоходом давал информацию, что получать кол-во патронов в оружии можно и без использования сторонних апдейтеров ... Что имелось ввиду: Смотрим 'se_item.script', в котором к счастью имеются все классы для оружия (кстати и класс физ.объекта там же). Да, в оригинальном скрипте в этих классах отсутствуют коды с методами STATE_Read|Write, но внеся эти коды мы видим, что они работают(!) и есть доступ к начальной части нет-пакета с секцией 'cse_abstract'. Причем, чтение/запись нет-пакетов происходит не только при старте/сейве игры или при спавне соотв. объекта, но и в процессе(!) игры. Применительно к задаче, которую ставил себе *Shoker*', достаточно было мониторить активный для ГГ ствол (его ID) и для этого оружия распарсивать пакет (точнее его самый конец) чтобы получать значение текущего кол-ва патронов в стволе. Причем(!) не нужно утруждать ни себя ни игру сторонними принудительными вызовами, объект (движек) сам вызывает метод STATE_Write в нужное время (при изменении кол-ва) и дает нам требуемые данные. Есть только минус - при стрельбе очередью периодичность вызова этого метода ниже 'единичного выстрела' и имеется локальная погрешность. Пример кода для чтения в SHoC: function se_weapon_magazined:STATE_Read(reader, iSize) cse_alife_item_weapon.STATE_Read(self, reader, iSize) --/ можно распарсить cse_abstract!!! end function se_weapon_magazined:STATE_Write(packet) cse_alife_item_weapon.STATE_Write(self, packet) --/ можно распарсить cse_abstract!!! if self.id == idWeaponActor then --/ это оружие активное для ГГ? packet:r_seek(packet:w_tell() -5) --/ for SHOC local iAmmoElapsed = packet:r_u16() --/ текущее кол-во патронов в стволе packet:r_seek(packet:w_tell() +3) --/ ставим читалку в конец пакета printf("se_weapon_magazined:STATE_Write:Wpn=[%s],AmmoElapsed=[%s]", self:name(), iAmmoElapsed) end end К чему это? К тому, что, как писал выше, немалое кол-во класcов объектов, параметры которых динамически меняются, имеют вызовы методов STATE_Read|Write для объектов в прцессе игры, а значит(!) и есть доступ к начальной части пакета из которой как минимум можно прочитать секцию 'cse_abstract'. А раз можно прочитать - то скорее всего можно ее и изменить и попробовать заставить прочитать объект этот измененный нет-пакет ... даже в процессе игры, а не только на ее старте/сэйве. К принудительному чтению/записи нет-пакетов можмейкерами из своих скриптов это не имеет отношения. Примечание: При необходимости (и возможности) принудительно вызвать для объекта его 'штатные' STATE_Read|Write можно, например, переводом объекта он-офф-лайн ... Изменено 27 Октября 2011 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Поделиться этим сообщением Ссылка на сообщение
Artos 99 Опубликовано 27 Октября 2011 (изменено) Dennis_Chikin Не нужно думать, что упомянув слово "Соль" - всем и всякому сразу и все ясно и известно. Например я, не плохо отношусь к НС, но чтобы разбитаться в деталях ... так что потрудитесь далее не удивляться неосведомленности мнигих в том, что вам ясно как свои пять пальцев. Из твоего пояснения ничего не понял, кто откуда выгоняется и за кем гоняется. Сорри. По денджерам: имеется конкретно схема 'xr_danger.script' и если потребно, то неслодно внести требуемые правки, дабы можно было в нужное время для нужного НПС сбрасывать иль изменять требуемое ... По отношениям: Если бы ты не только на НС был зациклен, то например, в том же HLC5, в котором есть и лечение раненых врагов и изменение отношений (и смена группировки вылесенного!) мог бы наблюдать, как 'групповые отношения' влияют на игру. Например ни что не влияет на отношения внутри группировки неписей, но если вылечить солдата и сменит ему группировку - свои же и пристрелят сразу, хотя их отношения и не изменялись. Также можешь легко убедиться, что сделав врагами того же Волка и сидящего у костра сталкера-новичка (в начале игры) - они будут мирно сосуществовать в своем гулаге и не кинутся убивать друг друга. В общем если не отпала нужда - объясняй 'на пальцах' применительно к понятным всем кодам и ситуациям. И повторю, 'не рабочесть метода' тут не при чем, просто это далеко не то, что тебе нужно и/или достаточно. Изменено 27 Октября 2011 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Поделиться этим сообщением Ссылка на сообщение
Artos 99 Опубликовано 27 Октября 2011 (изменено) malandrinus Попробую и на чистой игре проверить, хотя не возьму в толк - в чем именно в этом отношении имеется различие между каким-либо модом и чистой ... Тем более чтобы это проверить - все одно потребуется внести изменения, хотя бы для вывода в читаемый лог. Суть то все одна, в чистой ничего само собою не видно (нет в логе), а как только вносим изменение - это уже и не чистая ... Каков критерий, чтобы говорить не о причудах модмейкера, а о работе именно исходных кодов? Пока однозначно для физ.объектов (cse_alife_object_physic) при переводе выбранного объекта (экспериментировал с вентилятором Сидоровича) в оффлайн и обратно - автоматически вызываются функции STATE_Write|Read и корректно читается секция 'cse_abstract'. Вот этот лог получен после первого апдейта актора: se_item:se_physic:STATE_Write:=[trader_ventilyator_0000]:r_tell=64714633:w_tell=86 Print_Table:NetPacket(trader_ventilyator_0000): dummy16 = [1] section_name = [physic_object] name = [trader_ventilyator_0000] s_gameid = [0] s_rp = [254] position.<userdata>.x = [-243.89122009277] position.<userdata>.y = [-23.180002212524] position.<userdata>.z = [-133.19967651367] position = [vec(x=-243.891:y=-23.180:z=-133.200)] direction.<userdata>.x = [0] direction.<userdata>.y = [-0.26178956031799] direction.<userdata>.z = [0] direction = [vec(x=0.000:y=-0.262:z=0.000)] respawn_time = [0] unknown_id = [102] parent_id = [65535] phantom_id = [65535] s_flags = [96] version = [118] script_version = [7] unused = [0] spawn_id = [101] extended_size = [0] se_item:se_physic:STATE_Read:=[trader_ventilyator_0000/102]:Size=75:r_tell=86:w_tell=159 - что полностью до знака соответствует параметрам этого объекта из all.spawn'а. Примечание: А вот для оружия прочитать в процессе игры эту секцию пока не удалось ... Только из первого пакета можно получить начальную секцию, позже ... только без 'cse_abstract' удается прочитать, мешает 'мусор'. Почему то после первого пакета далее w_tell постоянно равен 2 (двум) и никак не могу определить начало пакета ... Изменено 27 Октября 2011 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Поделиться этим сообщением Ссылка на сообщение
Artos 99 Опубликовано 27 Октября 2011 (изменено) malandrinus Ну ... на то и модмейкеру голова, чтобы когда очень хотса - значит можно и поизвращаться ... Тот же физ-объект можно в игре удалить и вновь заспавнить на место удаленного, чтобы вызвать самый корректный первый пакет и его перепаковать. Но это все же уже изврат. P.S. В своих ковыряниях на эту тему НЕ использовал никаких скриптовых вызовов связанных с нет-пакетами для тестируемых объектоов. Хотя для активного оружия актора у меня как раз стоИт постоянное чтение из нет-пакета кол-ва патронов именно 'своим' скриптовым вызовом на чтение общего нет-пакета. Перепроверю с чистым переводом в офф-он ... Тут ты вероятно прав! Изменено 27 Октября 2011 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Поделиться этим сообщением Ссылка на сообщение
Artos 99 Опубликовано 27 Октября 2011 (изменено) malandrinus Неточно выразился ... В моде есть 'разрывные' патроны и чтобы определить, что именно они в стволе и именно пулей он них убит и должен 'взорваться' - мониторю текущий тип патрона в стволе (ammo_type) и по нему определяю секцию ... Штатных методов для этого нет. Перепроверил с оружием. Ты прав, это 'мои грабли' и 'штатные' вызовы в игре чтения/записи нет-пакетов пока тоже только при манипуляциях с онлайном обнаружил. P.P.S. Вот теперь, после обмена знаниями/навыками и ошибками, открыт путь к смене позиции и дирекции для объектов (неписей и пр.). Суть (для объектов в онлайне): - в подходящий момент отправляем объект в оффлайн и обратно в онлайн, одновременно выставив разрешающий флаг для чтения из нет-пакета секции 'cse_abstract' объекта и дав (запомнив) информацию по необходимым изменениям в координатах; - читаем в 'штатном' для объекта методе STATE_Read|Write нет-пакет и перепаковываем его с новыми параметрами. Изменено 27 Октября 2011 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Поделиться этим сообщением Ссылка на сообщение
Artos 99 Опубликовано 27 Октября 2011 (изменено) 7.9 Не торопись , пока информация дана скорее для опытных модмейкеров, которые предпочитают самостоятельно выбирать пути решения ... Вариантов может быть достаточно много. Дай хотя бы день-два на то, чтобы перепроверить отсутсвие каких-либо коллизий из-за подобного вмешательства в коды/алгоритмы игры. Пока могу сказать: - в модуль нет-пакетов (m_net_utils.script) добавлено чтение/изменение секции 'cse_abstract' для объектов (чтобы не плодить в каждом скрипте); - написан достаточно общий (в смысле применимости в модах) кусок кода для включения в штатные классы серверных объектов для чтения/перепаковки секции 'cse_abstract' в нет-пакетах (это по сути и один из вариантов 'установки флага' и 'задание новых параметров'); - опробовано на физ.объектах, сталкерах и монстрах ... Требуется некоторое время на проверку отсутствия коллизий с рестрикторами (если таковые прописаны) и иными нюансами (это по поводу 'неподходящих' моментов). Изменено 27 Октября 2011 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Поделиться этим сообщением Ссылка на сообщение
Artos 99 Опубликовано 27 Октября 2011 (изменено) *Shoker* О 'граблях' уже дал ответ ранее. Мониторинг текущей секции патронов в стволе ГГ, что связано с периодичностью вызовов чтения нет-пакета активного оружия внес ошибку в проверку наличия штатных вызовов чтения/записи нет-пакетов серверных объектов. Без 'моих' вызовов - штатных вызовов в процессе игры не было. Т.е. справедлив вывод, что штатные вызовы чтения/записи нет-пакетов для серверных объектов происходят ТОЛЬКО при загрузке/сохранении игры и при переходе объектов в онлайн (что может быть вызвано искуственно модмейкером в процессе игры). Изменено 27 Октября 2011 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Поделиться этим сообщением Ссылка на сообщение
Artos 99 Опубликовано 28 Октября 2011 (изменено) (возвращаясь к вопросу изменения дирекции и позиции для объектов) Итак, опыты с изменениями позиции для онлайновых объектов и направления закончились успешно. Пока фатальных коллизий не замечено. Ограничения в основном локальные и требуют просто например отрегистрации НПС от работ, дабы не возвращался ... иль подобного. Что требуется? 1. Коды чтения/записи секции 'cse_abstract'. Они размещены в общем модуле для чтения нет-пакетов: m_net_utils_111027 - примечание: конфиг файл (ltx) поместить в папку конфигов. 2. Внести в конец файла 'db.script' следующие коды: --/ ----------------------------------------------------------------- --/#+# Коды для работы с секцией 'cse_abstract' объектов --/ ----------------------------------------------------------------- tControlAbstract = {} --/ массив имен объектов для чтения/изменения секции 'cse_abstract' tCse_Abstract = {} --/ id-массив объектов и параметры секции 'cse_abstract' (Table[ID] = TableParams) tSwitchObj = {} --/ id-массив объектов для перевода 'online->offline->online' (аналог AMK 'convert_npc') --/ Подготовка к чтению/изменениям параметров в секции 'cse_abstract' function Add_Control_Abstract(idObj,tParams) --/< ID-объекта и таблица [с изменяемыми параметрами] local soObj = idObj and alife():object(idObj) --/ серверный объект if soObj and type(tParams) == 'table' then tControlAbstract[soObj:name()] = tParams --/ заносим в массив для чтения/изменения 'cse_abstract' if level.object_by_id(idObj) then --/ если в онлайне: alife():set_switch_online(idObj, false) alife():set_switch_offline(idObj, true) end tSwitchObj[idObj] = true --/ заносим в массив перевода объекта 'offline->online' end end --/ Редирект функции чтения/изменения секции 'cse_abstract' function Control_Abstract(...) if m_net_utils then m_net_utils.Control_Abstract(...) end end --/------------------------------------------------------------------ - они являются общими и вызываются из внешних скриптов. 3. Добавить в соответсвующие классы серверных объектов, для которых предполазается работа с секцией 'cse_abstract', в метод STATE_Write в самое начало строку: db.Control_Abstract(self,packet) --/#+# чтение/изменение секции 'cse_abstract' Например для сталкеров в 'se_stalker.script' добавляем так: function se_stalker:STATE_Write(packet) db.Control_Abstract(self,packet) --/#+# читаем/изменяем секцию 'cse_abstract' --/ ... последующий код end Аналогично и для монстров (se_monster.script) Для серверных классов у которых отсутствует данный метод - следует его добавить. Например для броников, оружия, физ.объектов в 'se_item.script' в каждый требуемый класс добавляем типа так: --/ Броники/костюмы class "se_outfit" (cse_alife_item_custom_outfit) --/ ... предыдущие методы --/#+# добавляем function se_outfit:STATE_Write(packet) db.Control_Abstract(self,packet) --/#+# чтение/изменение секции 'cse_abstract' cse_alife_item_custom_outfit.STATE_Write(self, packet) end ... --/ Физобъекты class "se_physic" (cse_alife_object_physic) --/ ... предыдущие методы --/#+# добавляем function se_physic:STATE_Write(packet) db.Control_Abstract(self,packet) --/#+# чтение/изменение секции 'cse_abstract' cse_alife_object_physic.STATE_Write(self, packet) end 4. (для кого-то, кто не имеет аналогов AMK-кодов - самое сложное) Для работы с уже заспавненными объектами - требуются коды/алгоритм перевода объектов из оффлайна в онлайн. В АМК-моде это табличка 'convert_npc' и коды по работе с ней. Суть - если объект в онлайне требуется переводить его в оффлайн и обратно таким образом, чтобы вызывался метод STATE_Write для этого объекта. P.S. Примен кода из Simbion'а: --/ ----------------------------------------------------------------- --/ Check Switch NPCs/Items (On/Off Line) --/ ----------------------------------------------------------------- local tSwitchCnt = {} --/ массив-счетчик local tSwitchRe = {} --/ массив для перевода объектов он-офф-лайн function SwitchOffOn() --/< вызов из апдейта актора if not next(db.tSwitchObj) then return end --/> --/ локальная функция чистки local Clear = function(id) --/ чистка db.tSwitchObj[id] = nil tSwitchCnt[id] = nil tSwitchRe[id] = nil end -- local sim = alife() for id,v in pairs(db.tSwitchObj) do if sim:object(id) then --/ объект в игре if level.object_by_id(id) then --/ объект в он-лайне if v == false then --/ флаг завершения переключения Clear(id) --/ чистка else --/ ожидание перехода в офф-лайн (1-ая фаза) if not tSwitchCnt[id] or tSwitchCnt[id] < 48 then tSwitchCnt[id] = (tSwitchCnt[id] or 0) +1 else --/ макс. кол-во апдейтов актора (TODO: уточнить!) if tSwitchRe[id] then printf("SwitchOffOn:StopToOff:Id=[%s],Obj=[%s],MaxCnt=[%s]:<%s>", id, sim:object(id):section_name(), tSwitchCnt[id], "Warning!") Clear(id) --/ чистка else printf("%s:SwitchOffOn:StopToOff:Id=[%s],Obj=[%s],MaxCnt=[%s]:<%s>", sModule, id, sim:object(id):section_name(), tSwitchCnt[id], "Info!") --/ повторный перевод в офф-лайн sim:set_switch_online (id, false) sim:set_switch_offline(id, true) sim:set_interactive (id, false) --/#?# tSwitchRe[id] = true tSwitchCnt[id] = 16 end end end else --/ объект в офф-лайне if v == true then --/> переводим в он-лайне db.tSwitchObj[id] = false --/ переключаем флаг sim:set_switch_online (id, true) sim:set_switch_offline(id, false) sim:set_interactive (id, true) --/#?# tSwitchRe[id] = nil else --/ ожидание перехода в он-лайн (2-ая фаза) if not tSwitchCnt[id] or tSwitchCnt[id] < 96 then tSwitchCnt[id] = (tSwitchCnt[id] or 0) +1 else --/ макс. кол-во апдейтов актора (TODO: уточнить!) if tSwitchRe[id] then printf("SwitchOffOn:StopToOn:Id=[%s],Obj=[%s],MaxCnt=[%s]:<%s>", id, sim:object(id):section_name(), tSwitchCnt[id], "Warning!") Clear(id) --/ чистка else printf("%s:SwitchOffOn:StopToOn:Id=[%s],Obj=[%s],MaxCnt=[%s]:<%s>", sModule, id, sim:object(id):section_name(), tSwitchCnt[id], "Info!") --/ повторный перевод в офф-лайн sim:set_switch_online (id, true) sim:set_switch_offline(id, false) sim:set_interactive (id, true) --/#?# tSwitchRe[id] = true tSwitchCnt[id] = 64 end end end end else --/ объект исчез из игры printf("SwitchOffOn:NOT_NPC:Id=[%s],Flg=[%s],Cnt=[%s]:<%s>", id, db.tSwitchObj[id], tSwitchCnt[id], "Warning!") Clear(id) --/ чистка end end end --/ ----------------------------------------------------------------- Ну и далее можно пользоваться ... Пример скриптового спавна с изменением направления для заспавненного объекта: function Spawn_and_Change_Dir() --/ Спавним курточку новичка на тумбочку в подвальчике деревни новичков (на Кордоне) local soObj = alife():create("novice_outfit", vector():set(-213.0,-22.3,-127.4), 40605, 59) if soObj then --/ разворачиваем на 180град (3.14) local vDir = vector():set(0,3.14,0) --/ направление: 'воротничком к стене' --/ заносим в массив для изменения направления: db.tControlAbstract[soObj:name()] = { direction = vDir } end end Пример перемещения объекта (смена позиции и/или направления): function Change_PosDir() --/ Переносим вентилятор из каморки Сидоровича на тумбочку в подвальчике деревни новичков (на Кордоне) local soObj = alife():object("trader_ventilyator_0000") --/ находим в игре серверный объект вентилятора if soObj and level.object_by_id(soObj.id) then --/ нашли и он на текущей локации? local vPos = vector():set(-213.0,-22.3,-127.4) --/ координаты тумбочки в подвальчике local vDir = vector():set(0,3.14,0) --/ направление: 'лопастями от стены' --/ вызываем функцию добавления в массив для изменения позиции и направления: db.Add_Control_Abstract( soObj.id, { position = vPos, direction = vDir } ) end end Для объектов, не имеющих скриптывых классов (отсутствует function se_OBJECT:STATE_Write(packet) ) - данный метод не применим. Для всех остальны- по сути теперь скриптовой спавн ничем не отличим по возможностям от спавна в 'all.spawn' ! Кстати, примечание: Менять позицию онлайновым неписям и монстрам не обязательно через 'cse_abctract' - похоже достаточно в нужное время (пока в оффлайне) им просто переписать 'position' для их серверного объекта ... Изменено 28 Октября 2011 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Поделиться этим сообщением Ссылка на сообщение
Artos 99 Опубликовано 28 Октября 2011 (изменено) _Призрак_ Минимальное изменение в любом случае требуется - это вызов кодов для парсинга начальной части нет-пакета и ее перепаковки. Для физ объекта это будет примерно так: Добавляем в исходный класс физ.объктов код: class "se_physic" (cse_alife_object_physic) --/ ... предыдущие методы --/#+# добавляем function se_physic:STATE_Write(packet) if self.name() == "my_object_name" then m_net_utils.Control_Abstract(self,packet) --/#+# чтение/изменение секции 'cse_abstract' end cse_alife_object_physic.STATE_Write(self, packet) end Если тебе требуется только для спавнящегося объекта - то более, кроме модуля нет-пакетов тебе ничего не требуется. В соответствующем месте в момент спавна своего объекта формируешь вызов: db.tControlAbstract = {} db.tControlAbstract[soObj:name()] = { direction = vDir } (см. пример) Если же имеешь ввиду 'объект уже в игре' - то ... потребуются коды перевода из онлайна в оффлайн и обратно. Хотя для случая 'при старте игры' - то можно также минималом обойтись. Изменено 28 Октября 2011 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Поделиться этим сообщением Ссылка на сообщение
Artos 99 Опубликовано 29 Октября 2011 (изменено) *Shoker* Во-первых, это всего лишь рабочий вариант, который хотя и проверен, но все же в разработке. 'Увековечивать' его не считаю нужным. Это всего лишь текущий материал для других модмейкеров, а не коды для игроков, которым взбрело в голову поковыряться в игре. Во-вторых, не писал и не собираюсь каких-либо уроков/статей/наставлений ... Все приходяще и то, что написано вчера - завтра становится устаревшим а порой и вредным. Полезное - само не забудется ... В-третьих, кто ищет - тот всегда найдет, а если не находит - значит и нет особой нужды ... По телепортации объектов на другие уровни: Телепортировать объект с текущего уровня на другой в общем-то затруднений не вызывает, полный алгоритм и коды для примера позже может быть выложу. А вот если наоборот, т.е. с неактивных локаций на текущую - тут посложнее. При загрузке игры/сэйва или типа при создании сэйва подобное вполне возможно. Над этим пока веду работу ... Есть некоторые идейки как и в процессе игры перемещать объекты с других на текущую локацию, но ... пока не все ясно. Добавлено через 2 мин.: FLIKER Кроме выложенного куска лога с фатал-еррором требуются строки из лога выше этой секции. Иначе - гадай на кофейной гуще. Добавлено через некоторое время: Вопрос к знатокам: Для предметов классов cse_alife_item_document (II_DOC) и cse_alife_item_pda (D_PDA/S_PDA) имеется параметр 'info_portion', который в исходной игре никак не задействован (пустая строка). Какова должна быть строка в конфиге предметов указанных классов, чтобы этот параметр считывал заданное значение, а не оставался пустым? Примечание: Очень не хочется быть привязанным только к all.spawn'у или перезаписывать нет-пакеты нужных объектов, чтобы использовать данный параметр. Изменено 29 Октября 2011 пользователем ColR_iT "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Поделиться этим сообщением Ссылка на сообщение