EventHandler ON_NPC_DELETED(deleted_def, i0, i1, maker0, reply) {
if (deleted_def.respawn_time != 0) {
if (myself.maximum_npc >= myself.npc_count + 1) {
if (AtomicIncreaseTotal(deleted_def, 1, 1)) {
deleted_def.Spawn2(1, deleted_def.respawn_time, deleted_def.respawn_rand);
}
}
}
}
public boolean AtomicIncreaseTotal(final SpawnDefine define, final int count, final int unk)
{
lock.lock();
//if(maximum_npc < npc_count + count)
//return false;
if(define.getTotal() < define.getNpcCount() + count)
return false;
//npc_count += count;
define.increaseNpcCount(count);
lock.unlock();
return true;
}
Расходимся, барин не поделится.Вы сейчас пытаетесь получить на халяву те функции, которые люди реверсят годами, из l2npc server. Я думаю никто на ваши вопросы не ответит. Бесплатно по крайней мере. Аи это всего лишь '' исходный код минимального исходного кода'', по крайней мере я для себя так считаю, npc сервера птс. Нет, конечно если есть доброжелатели поделится реверсом этих функций, я не против, я не стану, извините. Да ещё чтобы это пытались на джаве повторить.
Дефольт извини, конечно, для тебя наверное это уже раз плюнуть. Я только начал дизасемблить птс, не так давно, и считаю, что любая инфа из приложений птс, не должна так просто попадать в шару. Если я не прав, извини.Расходимся, барин не поделится.
а такие персонажи с пеленок уже все знают и умеют)Чтоб с тобой так же никто не делился и не помогал ни в чем - надолго бы тебя хватило?
1) Yes these functions add these npcs to the party. Handlers like PARTY_ATTACKED / PARTY_DIED / etc are triggered by the master npc or npcs that were created by createprivates().Здравствуйте. Пытаюсь понять логику работы Npc и Spawn движка в ПТС-ах, и по некоторым вопросам уже весь мозг сломал в догадках и предположениях. А посему, любые подсказки от знающих людей были бы крайне ценными. Вопросы такие:
1) Те, кто спавнятся функцией CreateOnePrivateEx(...) по сути являются такими же миньонами, как и созданные функцией CreatePrivates() и добавляются в пати с нпц, чья аишка вызвала эту функцию? Или это просто функция для спавна моба в том же мейкере, где и тот нпц, через чью аишку идет спавн, и призывающий с призванным никакими пати не связаны?
2) В какую группу мейкера(SpawnDefine) добавляются нпц, которые не были изначально прописаны в npcpos, а были доспавнены АИшкой через CreatePrivates() или CreateOnePrivateEx(...)? Ведь тот же миньон далеко не всегда исчезает сразу же после удаления хозяина, но если сказать мейкеру убрать всех мобов в том или ином SpawnDefine - все призванные аишками нпц должны также удалиться. А для этого им, по идее, нужно принадлежать к тому же SpawnDefine. Но при этом, если посмотреть, как устроен контроль респа в том или ином дефайне мейкера, то возникают вопросы. Например, код из default_maker:
C-подобный:EventHandler ON_NPC_DELETED(deleted_def, i0, i1, maker0, reply) { if (deleted_def.respawn_time != 0) { if (myself.maximum_npc >= myself.npc_count + 1) { if (AtomicIncreaseTotal(deleted_def, 1, 1)) { deleted_def.Spawn2(1, deleted_def.respawn_time, deleted_def.respawn_rand); } } } }
Он принимает ссылку на SpawnDefine удаленного моба и, как я понимаю, вешает отложенный таск на спавн моба. Но это ведь должно распространяться только на "родных" мобов этого дефайна. И если "доспавненные" аишкой мобы находятся в той же группе, то как оно отличает, удален родной моб или доспавненный? А если доспавненные мобы не добавляются в ту же группу, где и владелец призвавшей его аишки, то каким образом сервер понимает, каких доспавненных нпц нужно удалить при деспавне всего Define? Вот это противоречие заставляет меня ломать мозг в догадках, как оно на самом деле устроено и куда добавляются такие вот "доспавненные" нпц.
3) Хотелось бы точно знать, как работает функция мейкера AtomicIncreaseTotal(SpawnDefine, int, int). Это просто потокобезопасная реализация примерно такого кода? Она проверяет и увеличивает только пару define.total и define.npc_count или учитывает также и maximum_npc и npc_count самого мейкера? Если учитывает счетчики мейкера - зачем тогда перед ней обычно идут прямые проверки на maximum_npc мейкера в их аишках? А если нет, то значит атомарное увеличение счетчика заспавненных в мейкере мобов происходит где-то "под капотом" в ядре?
Java:public boolean AtomicIncreaseTotal(final SpawnDefine define, final int count, final int unk) { lock.lock(); //if(maximum_npc < npc_count + count) //return false; if(define.getTotal() < define.getNpcCount() + count) return false; //npc_count += count; define.increaseNpcCount(count); lock.unlock(); return true; }
4) Не смог понять, как ПТС-ка определяет статус дружественности\враждебности того или иного нпц по отношению к игроку. Не агрессивности, а именно того, с кем бы без ctrl говоришь, а кого бьешь, кого задевают массухи, а кого нет. В АИшках и пара метрах npcdata толком не нашел параметров, намекающих на такой смысл. Думал, дело в типах, прописанных в нпцдате(типа boss, warrior, citizen, zzoldagu) как аналогов Npc, Monster, RaidBoss, Minion в яве. Но в результате тестов выяснил, что двух разных нпц типа citizen воспринимает по-разному - одного как моба и пытается сразу бить, а второго - как нпц, с которым персонаж пытается говорить. Так где же прописывается этот статус условно npc/monster в ПТС?
5) Есть четкий список возможных хендлеров типа ON_NPC_DELETED, ON_NPCPOS_EVENT и т.д. Однако. в одних АИшках они прописаны с одной сигнатуркой, в других - с другой, и вариаций могут быть сотни. Зачастую, они таким образом просто объявляют локальные переменные метода в его сигнатурке - это я понимаю. Но есть ли какой-то хитрый способ узнать некую базовую сигнатуру, то есть, аргументы, которые ядро передает всегда в тот или иной хендлер, чтобы отличить нормальные аргументы от таких вот "объявлений локальных переменных"? Или только анализировать каждое применение вручную и пытаться прослеживать закономерности, делая из них вывод? Нужно это, разумеется, для формирования правильной структуры аишек и взаимодействия ядра с ними в своей говнояве, при попытке реализации оффлайк-структуры мейкеров/аишек мейкеров/аишек нпц с их частичным парсом + постепенным допилом руками.
Это так или иначе уже делалось на java, не мы первые и не мы последние занимаемся подобным мазохизмом. Реализовать можно разными способами, какой-то будет лучше, какой-то хуже, но результат по итогу один и тот же. От ответов в данной теме зависит только то, насколько похожей будет структура кода. Просто наткнулись на парочку непонятных моментов и дабы до конца сложить картинку, решили задать вопрос тут. Нет желания делиться информацией - не делитесь.Вы сейчас пытаетесь получить на халяву те функции, которые люди реверсят годами, из l2npc server. Я думаю никто на ваши вопросы не ответит. Бесплатно по крайней мере. Аи это всего лишь '' исходный код минимального исходного кода'', по крайней мере я для себя так считаю, npc сервера птс. Нет, конечно если есть доброжелатели поделится реверсом этих функций, я не против, я не стану, извините. Да ещё чтобы это пытались на джаве повторить.
Я клоню к тому, что когда ты задавал вопросы - тебе на них весьма подробно отвечали и давали советы, а не писали: "мы тут годами сю изучаем, поэтому делиться не будем". Разве не так?Дефольт извини, конечно, для тебя наверное это уже раз плюнуть. Я только начал дизасемблить птс, не так давно, и считаю, что любая инфа из приложений птс, не должна так просто попадать в шару. Если я не прав, извини.
4)1) Yes these functions add these npcs to the party. Handlers like PARTY_ATTACKED / PARTY_DIED / etc are triggered by the master npc or npcs that were created by createprivates().
4) can_be_attacked= 0 / 1 (npcdata parameter)
Человек реверсит ПТС, делает важную работу и видимо в суматохе подзабыл как на этой же площадке ему давали информацию без всяких претензий и упреков. Вернуться к выполнению функции после хука.Я клоню к тому, что когда ты задавал вопросы - тебе на них весьма подробно отвечали и давали советы, а не писали: "мы тут годами сю изучаем, поэтому делиться не будем". Разве не так?
//Это комьюнити для того и создано, что бы люди находили ответы на вопросы. Не можешь\не хочешь? Проходи мимо.
Hmm, which one? Can you tell me the NPC ID?4)
RU: Почему 2 NPC sitizen имеющие can_be_attacked=0, ведут себя по разному? Один может быть атакован без ctrl, а второй выбрасывает диалоговое окно.
EN: Why do 2 sitizen NPCs with can_be_attacked=0 behave differently? One can be attacked without ctrl, while the second one throws out a dialog box.
RU: Купол и почти любой NPC из мирки, например, телепорт. Купол саммонили через команду. Как будто что-то еще влияет.Hmm, which one? Can you tell me the NPC ID?
Все НПЦ изначально имеющие мейкер и заспавненные через его механизмы, спавнят миньонов в тот же мейкер.1) Те, кто спавнятся функцией CreateOnePrivateEx(...) по сути являются такими же миньонами, как и созданные функцией CreatePrivates() и добавляются в пати с нпц, чья аишка вызвала эту функцию? Или это просто функция для спавна моба в том же мейкере, где и тот нпц, через чью аишку идет спавн, и призывающий с призванным никакими пати не связаны?
Миньоны спавнятся в тот же SpawnDefine, что и их лидер. Количество НПЦ в SpawnDefine не ограничено, но не может превышать лимит maximum_npc для мейкера. Т.е например, если в мейкере лимит 4 моба, то лидер сможет породить только 3 миньонов, после чего все дальнейшие попытки будут фейлится. Пример: ГК(Кларисса например), которая порождает Аллегрию. Лимит на 3 штуки Аллегрии, это как раз ограничения maximum_npc мейкера.2) В какую группу мейкера(SpawnDefine) добавляются нпц, которые не были изначально прописаны в npcpos, а были доспавнены АИшкой через CreatePrivates() или CreateOnePrivateEx(...)? Ведь тот же миньон далеко не всегда исчезает сразу же после удаления хозяина, но если сказать мейкеру убрать всех мобов в том или ином SpawnDefine - все призванные аишками нпц должны также удалиться. А для этого им, по идее, нужно принадлежать к тому же SpawnDefine. Но при этом, если посмотреть, как устроен контроль респа в том или ином дефайне мейкера, то возникают вопросы. Например, код из default_maker:
define.total фиксированное значение и не может быть изменено.3) Хотелось бы точно знать, как работает функция мейкера AtomicIncreaseTotal(SpawnDefine, int, int). Это просто потокобезопасная реализация примерно такого кода? Она проверяет и увеличивает только пару define.total и define.npc_count или учитывает также и maximum_npc и npc_count самого мейкера? Если учитывает счетчики мейкера - зачем тогда перед ней обычно идут прямые проверки на maximum_npc мейкера в их аишках? А если нет, то значит атомарное увеличение счетчика заспавненных в мейкере мобов происходит где-то "под капотом" в ядре?
Я себе сделал абстрактный класс, variables, который объявляет все переменные из сигнатур, кроме тех, которые могут быть параметрами хэндлеров и наследую от нее все скрипты ИИ. Таким образом, я могу передавать в хендлеры только шаред-параметры.5) Есть четкий список возможных хендлеров типа ON_NPC_DELETED, ON_NPCPOS_EVENT и т.д. Однако. в одних АИшках они прописаны с одной сигнатуркой, в других - с другой, и вариаций могут быть сотни. Зачастую, они таким образом просто объявляют локальные переменные метода в его сигнатурке - это я понимаю. Но есть ли какой-то хитрый способ узнать некую базовую сигнатуру, то есть, аргументы, которые ядро передает всегда в тот или иной хендлер, чтобы отличить нормальные аргументы от таких вот "объявлений локальных переменных"? Или только анализировать каждое применение вручную и пытаться прослеживать закономерности, делая из них вывод? Нужно это, разумеется, для формирования правильной структуры аишек и взаимодействия ядра с ними в своей говнояве, при попытке реализации оффлайк-структуры мейкеров/аишек мейкеров/аишек нпц с их частичным парсом + постепенным допилом руками.
Большое спасибо за столь детальное объяснение. Временно, для меня это неактуально, так как, пока что, занимаюсь другими вопросами, но все равно интересно. Да и будет актуально в будущем, так как хочу еще вернуться к этой теме. Судя по скринам, ты прилично так заморочился - респект! А мне вот и хочется, и колется реализовать нечто подобное. Не только из-за сложности(она компенсируется интересом), но и из-за того, что декомпильнутый код из AI.obj не всегда корректен. Пока переписывал движок инстов, с перфекционизмом желая 100% правильно их реализовать, смотря АИшки каждого мейкера, босса и особенрного моба в них, не раз замечал логические противоречия. То есть, там был код написан так, что непонятно, как он вообще работает. От багов в коде и фактически игре, до моментов, когда в коде белиберда, но в игре все адекватно по факту. И не угадаешь, сколько там таких приколов. Да и некоторые моменты мне не очень нравятся в ПТС-структуре. Например, те же квесты разбиты по взаимодействию АИшек тучи пнц, но нет единого класса квеста, объединяющего по смыслу все или большую часть того, что с ним связано. Аналогично в инстанс-зонах нет некого единого класса АИшки инста - оно разбито по куче АИшек нпц и мейкеров. С точки зрения "спарсил -> работает" - это норм подход, но в плане удобства поддержки такого кода - не очень.Я хз, актуально еще для тебя это или нет)
Для начала открою небольшую тайну. Скрипты ИИ из AI.obj, это не ИИ в привычном нам смысле слова. Это скрипты, которые управляются из общего игрового ИИ. Т.е по факту, они не наследуются от AbstractAI. Из наследников AbstractAI объявляются события, которые "опускаются" в скрипты и выполняются там. Т.е пример. Моб получает урон, умирает. В основном ИИ, например NpcAI, происходят все базовые обработки смерти и от туда "спускается" метод MY_DYING в скрипт, который уже проходит по супервызовам насколько ему это позволяют.
Все НПЦ изначально имеющие мейкер и заспавненные через его механизмы, спавнят миньонов в тот же мейкер.
Миньон - это такой же моб, но имеющий двухстороннюю связь с мобом, который его засумонил. Это действительно, что-то типа пати, т.к эта связь обрабатывается корректно для проверок в скилла типа party и party_pledge
CreateOnePrivateEx в качестве одного из параметров принимает как раз таки ИИ моба, который управляет его дальнейшим поведением. Если он наследуется от party_private, то он как правило обретает типичные особенности поведения миньона, но это не обязательно. Моб заспавненный через CreateOnePrivateEx может быть каким угодно.
Миньоны спавнятся в тот же SpawnDefine, что и их лидер. Количество НПЦ в SpawnDefine не ограничено, но не может превышать лимит maximum_npc для мейкера. Т.е например, если в мейкере лимит 4 моба, то лидер сможет породить только 3 миньонов, после чего все дальнейшие попытки будут фейлится. Пример: ГК(Кларисса например), которая порождает Аллегрию. Лимит на 3 штуки Аллегрии, это как раз ограничения maximum_npc мейкера.
Существование миньонов после смерти мастера управляется через ИИ миньонов. Как правило, это таймер 1004, который запускается на интервал в 20с, и в случае если миньон не в бою, деспавнит его, но могут быть и другие варианты в зависимости от ИИ. Общее правило - это то, что миньоны принудительно деспавнятся после респавна мастера. Также, респавн и спавн миньонов управляется общим движком респавна и может быть отложен на определенное время из ИИ.
define.total фиксированное значение и не может быть изменено.
AtomicIncreaseTotal увеличивает только npc_count для мейкера. Значения внутри метода не валидируются, все проверки происходят из кода в ИИ. Да, это потокобезопасный код.
Я себе сделал абстрактный класс, variables, который объявляет все переменные из сигнатур, кроме тех, которые могут быть параметрами хэндлеров и наследую от нее все скрипты ИИ. Таким образом, я могу передавать в хендлеры только шаред-параметры.
Посмотреть вложение 48625
Посмотреть вложение 48626
Посмотреть вложение 48627
Многое зависит от декомпилятора, а также от выбранного принципа разбора скриптов.декомпильнутый код из AI.obj не всегда корректен.
Я пока столкнулся с только одним не понятным вопросом, но успешно получилось его решить.не раз замечал логические противоречия
С точки зрения создания нового квеста - проблем нет, т.к по больше части все максимально просто в самом движке.Например, те же квесты разбиты по взаимодействию АИшек тучи пнц, но нет единого класса квеста, объединяющего по смыслу все или большую часть того, что с ним связано.
Да я тоже стараюсь изначально исходить из того, что в ai.obj все правильно, а это я дурак, но все равно находил там немало проблемных мест. Но я уже конкретики не вспомню, так как лазил туда последний раз ещё летом 2022-го. Кстати, по поводу навигации по классам и manual_pch интерфейсом - у нас мысли сошлись) Тоже использую такой метод на минималке(пока что, только SCE_PCH и имплементирую его в AbstractNpcAI и AbstractInzoneAIМногое зависит от декомпилятора, а также от выбранного принципа разбора скриптов.
Я взял за основной тезис, что скрипты ПТСа верные(это касается ai.obj и остального датапака), т.к они успешно работают на ПТС.
Следовательно, если у меня что-то не работает, то это не скрипты кривые, а я дурак. Поэтому почти с самого начала разработки, мой датапак выглядит вот так и я работаю с ним в формате read-only:
Посмотреть вложение 48775
Я пока столкнулся с только одним не понятным вопросом, но успешно получилось его решить.
Вы не можете просматривать ссылку пожалуйста воспользуйтесь следующими ссылками Вход или Регистрация
С точки зрения создания нового квеста - проблем нет, т.к по больше части все максимально просто в самом движке.
С точки зрения исправления старых квестов - проблем нет, т.к исправления вносятся централизовано, через внесение правок в декомпилятор и конвертер(который декомпил NASC собирает в читаемый Java)
С точки зрения навигации по классам, которые участвуют в квесте, то можно прикрутить manual_pch в качестве интерфейса с константами и наследоваться от него. В этом случае, можно в любой момент посмотреть, где используется та или иная константы. Это удобно и с точки зрения квестов, да и в целом.
Посмотреть вложение 48776
Посмотреть вложение 48777
В целом, если вдруг надумаешь пилить в этом направлении и будут вопросы, пиши в телегу) Поделюсь опытом, если сам уже к тому времени найду решение)
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?