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

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


Svoboда

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

*Shoker*

Да, упоминания про 'updskeleton_flags' нужно просто удалить из кодов.

Если есть желание можешь потестить новую версию:

m_net_utils_111015

- изменен формат получаемой таблицы нет-пакета. Параметры UPDATE выделены в субтаблицу 'Table.upd'

- изменена последовательность аргументов при вызове записи пакета: 'Table,soObj,Flag' -> 'soObj,Table'. Необходимость записи UPDATE_write определяется по наличию субтаблицы 'Table.upd'.

- введены общие функции: Get_NetPacket/Set_NetPacket, самостоятельно определяющие класс серверного объекта и выбирающие соотв.методы чтения/записи.

Т.о. чтение/запись возможны через единые общие методы, которым в качестве первого аргумента передается серверный объект, а вторым при чтении - флаг чтения полного пакета, а при записи - таблица для записи пакета.

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Поделиться этим сообщением


Ссылка на сообщение

Scarabay

Нож для НПС не юзаем. Хочешь сделать - приаттачивай к его руке и махай 'анимацией'.

В общем смотри схемы 'мордобоя' из модов и делай по аналогии.

 

 

Поправлю немного Desertir'а, нет никакой надобности добавлять 'лишний' аргумент (self) в коллбэк актору.

И так понятно, что юзает (who) именно он, а не кто иной.

Также несколько странная фраза:

Desertir: А вот "проверять, существует ли предмет, который потерян" вообще интересен
Если тому же 'батону' в конфиге прописать 'многопорционность', то для таких 'многократных' использований как раз проверка 'съеден' ли батон иль только 'надкушен' (в процессе поедания) - совсем не лишне!

Следует все же различать то, о чем говорит событие, а не додумывать его иль ориентироваться только на общие случаи. Правильным для 'отследить поедание' (см. вопрос) - достаточен коллбэк 'use_object', а вот для однозначности 'съеден' - тут уже без доп. проверки на исчезновение предмета из игры не обойтись.

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Поделиться этим сообщением


Ссылка на сообщение

*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)

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Поделиться этим сообщением


Ссылка на сообщение

*Shoker*

Странноватые вопросы возникают у тебя ... (по STATE_Read/Write). Вроде как даже пояснил ...

Как вообще возникают объекты в игре? Как они получают свои параметры? Как меняют свои параметры?

Это обшие вопросы и не имеют к теме отношения. Но все же поясню.

При старте игры из сэйва читаеся информация о всех динамических объектах, которые были в игре при сохранении. Для новой игры (НИ) информация о таких объектах берется из all.spawn'а.

Сервер создает объекты-заготовки соответствующего класса для всех объектов. На этом этапе это просто шаблоны с дефолтными параметрами и с единыи ID-65535 (т.е. игровой идентификатор пока не задан!).

Далее, в объекты-заготовки считываются (STATE_Read) их конкретные параметры и объекты расставляются по локациям, координатам и пр ...

После этого, полученные объекты считываются (STATE_Write) запущенным сервером, чтобы прочитать их параметры и определить какие объекты относятся к текущей локации.

Для объектов, которые биндятся и могут иметь сохраненные в сэйве параметры в pstor'ах - вновь запускается читалка (STATE_Read) и считываются эти параметры.

Естественно, после того, как сервер считал текущие параметры объектов на локации - вновь необходимо дать информацию по этим объектам в игру, т.е. клиентские объекты должны иметь текущий нет-пакет (STATE_Write).

Ну и т.д. ... Например для объекта 'оружие в рукаг ГГ' будет вызываться STATE_Read/Write периодически, что можно даже с некоторой погрешностью испорльзовать для счтывания текущего кол-ва патронов для этого объекта ... не задействуя сторонние апдейтеры.

 

Ну а модуль нет-пакетов не переопачивается каждый раз. Суть (на 95%) остается прежней.

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Поделиться этим сообщением


Ссылка на сообщение

*Shoker*

Скорость/ресурсоемкость в первую очередь определяется алгоритмом! Выбор конкретных функций и соответственно их суммарная скорость - производная от алгоритма.

 

1. Учись задавать вопросы так, чтлбы было желание ответить.

На вопрос типа: "Кто знает, почему в Сталкере разработчики ..." - кроме как ответа: "Поди к ним и спроси!", мне, например, давать не хочется ...

А вот вопрос: "В чем отличия/преимущества одного метода по сравнению с другим(и)" - и смыслом наполнен и задуматься заставляет и поделиться мнением/навыком побуждает!

 

2. Ты не задумывался над тем, что расстояние может быть и отрицательным? Конечно оказаться внутри сталкера/монстра/предмета ГГ не может, но внутри рестриктора, аномалии и т.п. - запросто!

Вычисление расстояния до некоей зоны и сравнение с аналогичными - имеет смысл в связке с радиусом зоны до центра которой (иль до периметра) измеряешь.

Есть еще и 2D-расстояние (distance_to_xz) - это чтобы и с высотою не промахнуться, ежели например, кто-то 'на 2-ой этаж забрался' ...

 

3. Ну а ускорять ... есть правило - если слишком много параметров/данных, то следует по-возможности отбросить те, которые в данной ситуации (в данное время) не обязательно учитывать или ими можно пренебречь.

Не знаю, что там у тебя с ГГ и аномалиями, но то, что ГГ может за некий период (напримет 15 сек) отбежать на некую лимитированную его возможностями дистанцию, дает возможность периодические (15 сек, а не 20 мсек!) делать выборки из общей таблицы и работать только с 'доступными' объектами/аномалиями. (Пример в известном тебе моде при обходе аномалий неписями ...). Т.о. вернулись в начало: оптимальный алгоритм всегда выигрывает ...

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Поделиться этим сообщением


Ссылка на сообщение

Dennis_Chikin

Заглянув в тему "Справочник по функциям и классам" (иль в lua_help.script) - можно увидеть, что работает с гейм-объектами. Если у тебя не работает - ищи причину у себя в неправильном применении метода.

Работоспособность метода не только для ГГ - подтверждают и оригинальная игра и моды ...

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Поделиться этим сообщением


Ссылка на сообщение

Все же стОит для простых смертных дать попроще пояснение, а то и запутаться могут:

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'ов - это уже тема иная ...

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Поделиться этим сообщением


Ссылка на сообщение

Возможность изменить '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) и аналогичными параметрами - изменяем, а результат только позже проявляется.

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Поделиться этим сообщением


Ссылка на сообщение

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' для объекта.

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Поделиться этим сообщением


Ссылка на сообщение

Dennis_Chikin

А почему ты считаешь, что изменив один параметр, и игнорируя наличие иных, ты достигнешь желаемого рузультата?

Не стоит забывать, что в игре многое и взаимосвязано и взаимозависимо.

Помимо взаимоотношений персоналий на них распространяются и общегрупповые правила и правила гулагов и прочее. Смотреть нужно в конкретной ситуации все взаимозависимые параметры и при необходимости менять и их.

А при необходимости даже и денжеры сбрасывать ... Не стоит думать, что игра все сама за модмейкера разрулит.

Приводи конкретную ситуацию (желательно применимо к исходной игре) и бум посмотреть ...

 

Не рабочий метод и отсутствие результата после применения метода - далеко не одно и то же.

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Поделиться этим сообщением


Ссылка на сообщение

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 можно, например, переводом объекта он-офф-лайн ...

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Поделиться этим сообщением


Ссылка на сообщение

Dennis_Chikin

Не нужно думать, что упомянув слово "Соль" - всем и всякому сразу и все ясно и известно. Например я, не плохо отношусь к НС, но чтобы разбитаться в деталях ... так что потрудитесь далее не удивляться неосведомленности мнигих в том, что вам ясно как свои пять пальцев. Из твоего пояснения ничего не понял, кто откуда выгоняется и за кем гоняется. Сорри.

 

По денджерам: имеется конкретно схема 'xr_danger.script' и если потребно, то неслодно внести требуемые правки, дабы можно было в нужное время для нужного НПС сбрасывать иль изменять требуемое ...

 

По отношениям: Если бы ты не только на НС был зациклен, то например, в том же HLC5, в котором есть и лечение раненых врагов и изменение отношений (и смена группировки вылесенного!) мог бы наблюдать, как 'групповые отношения' влияют на игру. Например ни что не влияет на отношения внутри группировки неписей, но если вылечить солдата и сменит ему группировку - свои же и пристрелят сразу, хотя их отношения и не изменялись.

Также можешь легко убедиться, что сделав врагами того же Волка и сидящего у костра сталкера-новичка (в начале игры) - они будут мирно сосуществовать в своем гулаге и не кинутся убивать друг друга.

 

В общем если не отпала нужда - объясняй 'на пальцах' применительно к понятным всем кодам и ситуациям. И повторю, 'не рабочесть метода' тут не при чем, просто это далеко не то, что тебе нужно и/или достаточно.

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Поделиться этим сообщением


Ссылка на сообщение

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 (двум) и никак не могу определить начало пакета ...

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Поделиться этим сообщением


Ссылка на сообщение

malandrinus

;) Ну ... на то и модмейкеру голова, чтобы когда очень хотса - значит можно и поизвращаться ...

Тот же физ-объект можно в игре удалить и вновь заспавнить на место удаленного, чтобы вызвать самый корректный первый пакет и его перепаковать.

Но это все же уже изврат.

 

P.S. В своих ковыряниях на эту тему НЕ использовал никаких скриптовых вызовов связанных с нет-пакетами для тестируемых объектоов. Хотя для активного оружия актора у меня как раз стоИт постоянное чтение из нет-пакета кол-ва патронов именно 'своим' скриптовым вызовом на чтение общего нет-пакета. Перепроверю с чистым переводом в офф-он ... Тут ты вероятно прав!

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Поделиться этим сообщением


Ссылка на сообщение

malandrinus

Неточно выразился ...

В моде есть 'разрывные' патроны и чтобы определить, что именно они в стволе и именно пулей он них убит и должен 'взорваться' - мониторю текущий тип патрона в стволе (ammo_type) и по нему определяю секцию ... Штатных методов для этого нет.

 

Перепроверил с оружием. Ты прав, это 'мои грабли' и 'штатные' вызовы в игре чтения/записи нет-пакетов пока тоже только при манипуляциях с онлайном обнаружил.

 

P.P.S.

Вот теперь, после обмена знаниями/навыками и ошибками, открыт путь к смене позиции и дирекции для объектов (неписей и пр.).

Суть (для объектов в онлайне):

- в подходящий момент отправляем объект в оффлайн и обратно в онлайн, одновременно выставив разрешающий флаг для чтения из нет-пакета секции 'cse_abstract' объекта и дав (запомнив) информацию по необходимым изменениям в координатах;

- читаем в 'штатном' для объекта методе STATE_Read|Write нет-пакет и перепаковываем его с новыми параметрами.

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Поделиться этим сообщением


Ссылка на сообщение

7.9

Не торопись ;) , пока информация дана скорее для опытных модмейкеров, которые предпочитают самостоятельно выбирать пути решения ... Вариантов может быть достаточно много.

Дай хотя бы день-два на то, чтобы перепроверить отсутсвие каких-либо коллизий из-за подобного вмешательства в коды/алгоритмы игры.

Пока могу сказать:

- в модуль нет-пакетов (m_net_utils.script) добавлено чтение/изменение секции 'cse_abstract' для объектов (чтобы не плодить в каждом скрипте);

- написан достаточно общий (в смысле применимости в модах) кусок кода для включения в штатные классы серверных объектов для чтения/перепаковки секции 'cse_abstract' в нет-пакетах (это по сути и один из вариантов 'установки флага' и 'задание новых параметров');

- опробовано на физ.объектах, сталкерах и монстрах ...

Требуется некоторое время на проверку отсутствия коллизий с рестрикторами (если таковые прописаны) и иными нюансами (это по поводу 'неподходящих' моментов).

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Поделиться этим сообщением


Ссылка на сообщение

*Shoker*

О 'граблях' уже дал ответ ранее.

Мониторинг текущей секции патронов в стволе ГГ, что связано с периодичностью вызовов чтения нет-пакета активного оружия внес ошибку в проверку наличия штатных вызовов чтения/записи нет-пакетов серверных объектов.

Без 'моих' вызовов - штатных вызовов в процессе игры не было.

Т.е. справедлив вывод, что штатные вызовы чтения/записи нет-пакетов для серверных объектов происходят ТОЛЬКО при загрузке/сохранении игры и при переходе объектов в онлайн (что может быть вызвано искуственно модмейкером в процессе игры).

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Поделиться этим сообщением


Ссылка на сообщение

(возвращаясь к вопросу изменения дирекции и позиции для объектов)

 

Итак, опыты с изменениями позиции для онлайновых объектов и направления закончились успешно. Пока фатальных коллизий не замечено. Ограничения в основном локальные и требуют просто например отрегистрации НПС от работ, дабы не возвращался ... иль подобного.

 

Что требуется?

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' для их серверного объекта ...

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Поделиться этим сообщением


Ссылка на сообщение

_Призрак_

Минимальное изменение в любом случае требуется - это вызов кодов для парсинга начальной части нет-пакета и ее перепаковки.

Для физ объекта это будет примерно так:

Добавляем в исходный класс физ.объктов код:

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 }

(см. пример)

 

Если же имеешь ввиду 'объект уже в игре' - то ... потребуются коды перевода из онлайна в оффлайн и обратно.

Хотя для случая 'при старте игры' - то можно также минималом обойтись.

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Поделиться этим сообщением


Ссылка на сообщение

*Shoker*

Во-первых, это всего лишь рабочий вариант, который хотя и проверен, но все же в разработке. 'Увековечивать' его не считаю нужным. Это всего лишь текущий материал для других модмейкеров, а не коды для игроков, которым взбрело в голову поковыряться в игре.

Во-вторых, не писал и не собираюсь каких-либо уроков/статей/наставлений ... Все приходяще и то, что написано вчера - завтра становится устаревшим а порой и вредным. Полезное - само не забудется ...

В-третьих, кто ищет - тот всегда найдет, а если не находит - значит и нет особой нужды ...

 

По телепортации объектов на другие уровни:

Телепортировать объект с текущего уровня на другой в общем-то затруднений не вызывает, полный алгоритм и коды для примера позже может быть выложу.

А вот если наоборот, т.е. с неактивных локаций на текущую - тут посложнее.

При загрузке игры/сэйва или типа при создании сэйва подобное вполне возможно. Над этим пока веду работу ...

Есть некоторые идейки как и в процессе игры перемещать объекты с других на текущую локацию, но ... пока не все ясно.

 

Добавлено через 2 мин.:

FLIKER

Кроме выложенного куска лога с фатал-еррором требуются строки из лога выше этой секции. Иначе - гадай на кофейной гуще.

 

Добавлено через некоторое время:

Вопрос к знатокам:

Для предметов классов cse_alife_item_document (II_DOC) и cse_alife_item_pda (D_PDA/S_PDA) имеется параметр 'info_portion', который в исходной игре никак не задействован (пустая строка).

Какова должна быть строка в конфиге предметов указанных классов, чтобы этот параметр считывал заданное значение, а не оставался пустым?

 

Примечание: Очень не хочется быть привязанным только к all.spawn'у или перезаписывать нет-пакеты нужных объектов, чтобы использовать данный параметр.

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Поделиться этим сообщением


Ссылка на сообщение
  • Недавно просматривали   0 пользователей

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