Как выглядит bypass teleport go to village?

не помню, правда. но была какая то проблема с выбором TeleportList правильного
 
не помню, правда. но была какая то проблема с выбором TeleportList правильного
Из того что я понимаю, L2J нужно было решить проблему привязки байпасов страницы к определенному npc. То есть таким образом можно сделать так что-бы когда байпас прилетит тут же и проверить во первых общялся ли игрок с нпц или нет, ну и дальше этот байпас отправить куда нужно.

Но это ведь можно все и на сервере делать, без участия модификаций байпасов. Сейчас L2J хранит список в памяти тех линков и байпасов (они не одно и то же) которые были отправленны игроку, и когда игрок посылает какой-то другой байпас это уже можно сразу же проверить (там немного сложнее, из-за определенных байпасов используемых например в community board). Но смысл то в том что можно отправлять игроку что угодно, главное то что сервер может это все понять.
 
Teleport request есть в первом сообщении. Он для другого.
ну на моей картинке три байпаса "teleport_request" "teleporttonpc_" "teleport_"
teleport_request "запрашивает" список телепортов (там запрос улетает в npc сервер)

teleport_ судя по логгерам "Teleport hack!!! char_name[%s]" "Teleport hack or something changed!!! char_name[%s]" и системным сообщениям "Недостаточно аден." "Недостаточно необходимых предметов." наверное и есть телепорт


по teleporttonpc_ затрудняюсь сказать что это но есть например в g_dimension_door_01.htm
HTML:
<html><head><body>
Dimensional Door:
<br>
An endless and mysterious vortex slowly spins before you.
<br>
<br>
<a action="bypass -h teleporttonpc_142">Jump in.</a>
<br>
</body></html>

других байпасов со словом teleport тут нет )
 
Спасибо за помощь. На мысль натолкнули.
 
Так выглядит 1 строчка из списка
Код:
<button align=left icon=teleport action="bypass -h teleport_5077863200_0_57_1209033476_3" msg="811;F;1010004"><fstring>1010004</fstring></button>

Это сам байпас
Код:
bypass -h teleport_5077863200_0_57_1209033476_3

-h - закроет окно при отправке пакета
teleport - сам хендлер для обработки байпаса
5077863200 - это просто адрес списка позиций в кэше PosList L2Server.exe. По умолчанию кэш ПУСТ, поэтому этот адрес напрямую зависит от того, как рано L2NPC запрашивает конкретный PosList (обычно из-за взаимодействия игрока с NPC).
0 - индекс элемента в PosList
57 - тип / предмет платы за телепорт (что должно быть потреблено — PosList содержит только суммы)
1209033476 - smartId (в жаве objId нпц)
3 - тип телепортации, где 3 означает «новичок (бесплатно)», 1 — стандартный, 2 — ивент coretime

msg="811;F;1010004 - то что появляется при нажатии на строчку телепорта

811 - sysMsgId
F - Fstring = NpcString
1010004 - NpcStringId

Итог - Вы перемещаетесь в локацию (Глудин). Продолжить?
 
по teleporttonpc_ затрудняюсь сказать что это но есть например в g_dimension_door_01.htm
это очередное извращение от корейцев - телепорт к нпс с заданным ид
просто разбирался как раз с этим, когда выяснял нафига нужен эффект i_summon_unique_npc, который имеется в 2 скиллах и спавнит вот как раз нпс с ид 141 и 142.
суть оного - заспавнить на сервере 2 нпс которые могут быть только в одном экземпляре - если есть предыдущий спавн, то он удаляется.
ну и потом тупо через их диалоги перемещаться между этими нпс.
 
Последнее редактирование:
Вам важно понять, что те ИИ, которые вы смотрите, это СКРИПТЫ. Обработка логики этих скриптов проходит в NASC-интерпретаторе, который содержит саму логику внутренних функций скрипта. Т.е всякие ShowPage(talker, fnYouAreChaotic);, Teleport(talker, Position, ShopName, "", "", ""); и еще полторы тысячи функций для НПЦ и мейкеров. Не разобрав логику этих функций, вы не сможете ее воспроизвести.
Как выглядит структура и bypass динамично формирующегося html для телепорта?
На примере ПТС скриптов обычного телепортера. Как выглядит цепочка телепорта.
1) НПЦ при инициализации NASC скрипта, регается в холдер как телепортер, предоставляя список допустимых видов ТП.
2) После разговора с этим НПЦ, отсылается стартовая страница, которая обычно содержит байпасс teleport_request
3) Когда в клиенте тыкается этот байпасс, обработчик байпассов на стороне сервера триггерит NASC хендлер TELEPORT_REQUESTED в скрипте этого НПЦ, передавая туда определенные аргументы.
4) В большинстве случаев, в хендлере TELEPORT_REQUESTED у телепортеров вызывается функция TeleportFStr, которая формирует страницу телепорта и отсылает ее в клиент в качестве HTML сообщения.
5) Ну и дальше при клике на ТП, клиент шлет байпасс teleport с параметрами, которые интерпретируются на сервере и обрабатываются уже не в наске.


Сначала, когда проходит загрузка NASC-скриптов, актор наска регается как телепортер:
Java:
default void RegisterTeleporterType(int type, int level) {
        switch (getNASCActor()) {
            case Npc npc_actor -> NpcTeleportTypeManager.getInstance().registerTeleporterType(npc_actor, ETeleporterType.list.get(type), level);
            case null, default -> Loggers.STATIC.error("Unsupported actor type!", new IllegalArgumentException());
        }

    }

После этого, когда проходит вызов функции телепорта, триггерится хендлер телепорта:
Java:
@Override
    public void TELEPORT_REQUESTED(ISharedCreature talker) {
        if (talker.transformID() == 111 || talker.transformID() == 112 || talker.transformID() == 124) {
            ShowPage(talker, "q194_noteleport.htm");
        } else {
            TeleportFStr(talker, "Position", ShopName, "", "", "", 57, 1000308, "", "", "", "", "");
        }
    }

Java:
    @Override
    public void TELEPORT_REQUESTED(ISharedCreature talker) {
        if (IsMyLord(talker) || HavePledgePower(talker, ppSetGate) && Castle_GetPledgeId() == talker.pledge_id() && talker.pledge_id() != 0) {
            if (talker.transformID() == 111 || talker.transformID() == 112 || talker.transformID() == 124) {
                ShowPage(talker, "q194_noteleport.htm");
            } else if (Agit_GetDecoLevel(decotype_teleport) == 11) {
                TeleportFStr(talker, "Position1", ShopName, "", "", "", 57, 1000308, "", "", "", "", "");
            } else if (Agit_GetDecoLevel(decotype_teleport) == 12) {
                TeleportFStr(talker, "Position2", ShopName, "", "", "", 57, 1000308, "", "", "", "", "");
            } else {
                ShowPage(talker, fnFuncDisabled);
            }
        } else {
            ShowPage(talker, fnNoAuthority);
        }
    }

И вот такая реализация. Тут ты сможешь найти и структуру html и примерную логику:
Java:
default void TeleportFStr(ISharedCreature sCreature, String telposlist, String shopname, String byePage, String clsMissMatchPage, String underAdenaPage, int nItemClassID, int fstrItemIndex, String p1, String p2, String p3, String p4, String p5) {
        switch (getNASCActor()) {
            case Npc npc -> {
                if (sCreature instanceof Player talker) {
                    if (telposlist == null || telposlist.isEmpty()) {
                        return;
                    }

                    int[][] position = TelPosListHolder.getInstance().getTelPosList(npc, telposlist);

                    Int2ObjectOpenHashMap<String> tpls;
                    String base_html = """
                    <html><body>&$556;<br><br><?teleport_list?><br></body></html>
                    <!--TEMPLET1
                    <a action="bypass -h teleport_<?list_id?>_<?list_pos?>_<?item_id?>_<?npc_index?>" msg="811;F;<?location?>"><?pos_index?><fstring><?location?></fstring></a><br1>
                    TEMPLET-->
                    <!--TEMPLET2
                    <a action="bypass -h teleport_<?list_id?>_<?list_pos?>_<?item_id?>_<?npc_index?>" msg="811;F;<?location?>"><?pos_index?><fstring><?location?></fstring> - <?count?> <fstring p1="<?p1?>" p2="<?p2?>" p3="<?p3?>" p4="<?p4?>" p5="<?p5?>"><?item_name?></fstring></a><br1>
                    TEMPLET-->
                    """;
                    tpls = LocalFiles.parseTemplate(base_html);
                    try (var f = talker.openFHTML()) {
                        f.set(tpls.get(0));
                        StringBuilder list = new StringBuilder();

                        final var ldt = LocalDateTime.now();

                        int day = ldt.getDayOfWeek().getValue();
                        int hour = ldt.getHour();

                        boolean lowPrice = nItemClassID == adena && day != 1 && day != 7 && (hour <= 12 || hour >= 22);

                        int common_level = NpcTeleportTypeManager.getInstance().getTeleporterLevel(npc, ETeleporterType.TELEPORTER_COMMON);
                        int coretime_level = NpcTeleportTypeManager.getInstance().getTeleporterLevel(npc, ETeleporterType.TELEPORTER_CORETIME);
                        int free_level = NpcTeleportTypeManager.getInstance().getTeleporterLevel(npc, ETeleporterType.TELEPORTER_FREE);

                        if (free_level >= 0 && (free_level == 0 || talker.getLevel() <= free_level)) {
                            String tpl = tpls.get(1);
                            for (int c = 0; c < position.length; c++) {
                                list.append(tpl.replace("<?list_id?>", String.valueOf(position.hashCode())).replace("<?list_pos?>", String.valueOf(c)).replace("<?item_id?>", "0").replace("<?npc_index?>", String.valueOf(npc.getObjectId())).replace("<?location?>", String.valueOf(position[c][0])).replace("<?pos_index?>", (c + 1) + ". "));
                            }
                        } else if (nItemClassID == olympiad_token && coretime_level >= 0 && (coretime_level == 0 || talker.getLevel() <= coretime_level)) {
                            String tpl = tpls.get(2);
                            for (int c = 0; c < position.length; c++) {
                                list.append(tpl.replace("<?list_id?>", String.valueOf(position.hashCode())).replace("<?list_pos?>", String.valueOf(c)).replace("<?item_id?>", String.valueOf(nItemClassID)).replace("<?npc_index?>", String.valueOf(npc.getObjectId())).replace("<?location?>", String.valueOf(position[c][0])).replace("<?count?>", String.valueOf(position[c][4])).replace("<?item_name?>", String.valueOf(fstrItemIndex)).replace("<?p1?>", p1).replace("<?p2?>", p2).replace("<?p3?>", p3).replace("<?p4?>", p4).replace("<?p5?>", p5).replace("<?pos_index?>", (c + 1) + ". "));
                            }
                        } else if (common_level >= 0 && (common_level == 0 || talker.getLevel() <= common_level)) {
                            String tpl = tpls.get(2);
                            for (int c = 0; c < position.length; c++) {
                                list.append(tpl.replace("<?list_id?>", String.valueOf(position.hashCode())).replace("<?list_pos?>", String.valueOf(c)).replace("<?item_id?>", String.valueOf(nItemClassID)).replace("<?npc_index?>", String.valueOf(npc.getObjectId())).replace("<?location?>", String.valueOf(position[c][0])).replace("<?count?>", String.valueOf(position[c][4] / (lowPrice ? 2 : 1))).replace("<?item_name?>", String.valueOf(fstrItemIndex)).replace("<?p1?>", p1).replace("<?p2?>", p2).replace("<?p3?>", p3).replace("<?p4?>", p4).replace("<?p5?>", p5).replace("<?pos_index?>", (c + 1) + ". "));
                            }
                        }

                        f.replace("<?teleport_list?>", list.toString());
                        f.showNpc(npc);
                    }
                }
            }
            case null, default -> Loggers.STATIC.error("Unsupported actor type!", new IllegalArgumentException());
        }

    }

Это реализация для ХФ.

Ага, это для ГМской трансформы скиллы. Ну и unique npc в целом так работает. Не только на ворота. Есть NPC определенные, которые могут быть только в одном экземпляре призваны, т.к повторный вызов ломает NASC. Т.е второй экземпляр тупо не заспавится, если существует первый. Их не много, но они есть.
Посмотреть вложение Запись экрана 2025-08-28 064910.mp4
 
Последнее редактирование:
Спасибо. Вот такой ответ и ждал. А откуда источник? Или сами исследовали?

Спасибо за развернутый ответ.
Про то что нужно хорошее понимание NASC вы правы все так. Но вопрос был про html файл. И вы и ChaosPaladin дали ответ на него за что огромное спасибо. Это именно то что нужно.
P.S. почему-то не могу увеличить вам репутацию в плюс. Запрет какой-то)
 
Последнее редактирование модератором:
Данный сайт использует cookie. Вы должны принять их для продолжения использования. Узнать больше…