Перейти к содержанию
Авторизация  

Кастомный Next Target с регулируемой дальностью (interface+ядро)


Описание

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

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

Спойлер

if(command.startsWith("наш байпасс посылаемый с интерфейса")){
            String[] idsh = command.substring(24).trim().split(" ");
            int dist = Integer.parseInt(idsh[0]);
            if (dist > 1200)
            {
                dist = 1200;
            }
            else if (dist < 400)
            {
                dist = 400;
            }
            List<L2Character> nextMob = new FastList<L2Character>();

            for (L2Character players : player.getKnownList().getKnownCharactersInRadius(dist))
            {
                if (players.isMonster() && players.isAttackable() && !players.isDead() && players.getCurrentHp()>=0 && players != player.getTarget())
                {
                    nextMob.add(players);
                }
            }
            int choice = Rnd.nextInt(nextMob.size());
            if (choice > 0) {
                L2Character ftarget = nextMob.get(choice);
                player.setTarget(ftarget);
                player.sendPacket(new MyTargetSelected( ftarget.getObjectId(), 0));
                StatusUpdate su = new StatusUpdate( ftarget.getObjectId());
                su.addAttribute(StatusUpdate.CUR_HP, (int) ftarget.getStatus().getCurrentHp());
                su.addAttribute(StatusUpdate.MAX_HP, ftarget.getMaxHp());
                player.sendPacket(su);
            }

 

Спойлер

        if(bypass.startsWith("_bbsntarget")){
            StringTokenizer idsh = new StringTokenizer(bypass, " ");
            idsh.nextToken();
            int dist = Integer.parseInt(idsh.nextToken());
            if (dist > 1400)
            {
                dist = 1400;
            }
            else if (dist < 400)
            {
                dist = 400;
            }
            List<Creature> nextMob;
            nextMob = new LazyArrayList<Creature>();

            for(Creature players : player.getAroundCharacters(dist, dist))
            {
                if (players.isMonster() && !players.isDead() && players.getCurrentHp()>=0 && players != player.getTarget())
                {
                    nextMob.add(players);
                }
            }
            int choice = Rnd.get(nextMob.size());
            if (nextMob.size() > 0) {
                Creature ftarget = nextMob.get(choice);
                player.setTarget(ftarget);
                player.sendPacket(new MyTargetSelected( ftarget.getObjectId(), 0));
                player.sendPacket(ftarget.makeStatusUpdate(StatusUpdate.CUR_HP, StatusUpdate.MAX_HP));
            }
        }

 

(!)Обратите внимание на мои условия, мне нужны были в таргете только монстры, для своих целей перепишите соответствующим образом. (да, у меня такой синтаксис что игроки это мобы, а мобы - это игроки, все в порядке) Так же заметьте, я ограничиваю максимальную дальность 1200, Вы можете этого не делать, либо задать свою. Я бы советовал ограничить максимальную дальность именно в ядре, ибо зная байпасс с интерфейса можно будет творить чудеса. Так же вопрос: нужно ли принудительно обновлять хп/мп таргета, если Вы уже шлете пакет MyTargetSelected? - На адекватных сборках может и нет, а вот у меня были проблемы пока так не сделал.

Так же Вы можете добавить проверку на видимость целей, что-то вроде:
 

GeoData.getInstance().canSeeTarget(activeChar, nextMob)

Почему я такую не добавил? Об этом в следующей кулстори расскажу.

Теперь в интерфейсе прикрутим в функцию OnLoad() следующее:
(здесь тоже довольно извращенная и чрезмерно нагроможденная конструкция, опять же скорее для наглядности, адекватно на это посмотреть и переписать нормально, а не копировать):
 

    nrage(int(class'UIAPI_EDITBOX'.static.GetString("тут адрес нашего окна")));

Сама функция nrage:
 

function nrage(int valueX)
{
    if ( valueX < 400) {
        NTrange = 400;
    }
    if ( valueX > 1200) {
        NTrange = 1200;
    }
    else
    {
        NTrange = valueX;
    }
}

И наш отправляемый байпас:

    RequestBypassToServer("наш байпасс посылаемый с интерфейса "$ NTrange);

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

var EditBoxHandle     e_autoMacroRange;
var MacroListWnd* script_mc;
.....
    e_autoMacroRange = GetEditBoxHandle("Ваше окно");
    script_mc = MacroListWnd(GetScript("MacroListWnd"));

*на всякий случай: это я тяну с другого класса скрипт, и напомню, что Вы можете без проблем обойтись и без этого

Я сохраняю настройки по клику кнопки, потому нужен хендлер OnClickButton, и в нем наша кнопка:
 

        case "btnApply":
            OnApplyBtn();
        break;
....
сама функция кнопки (уже вне хендлера ,если что, наверное, это и так очевидно, но мне бы такая пометка жизнь спасти могла)

function OnApplyBtn()
{
    local int valueX
    if (e_autoMacroRange.GetString() != "")
    {
        valueX = int(e_autoMacroRange.GetString());
        if (valueX >= 400 && valueX <= 1200)
        {
            SetINIInt("MacroSettings", "AutoMacroRange", valueX, "PatchSettings");
            script_mc.nrage(valueX);
        }
    }
}

Для загрузки наших данных о дальности нексттаргета из файла:
 

function LoadINISets()
    ....
    GetINIString("MacroSettings", "AutoMacroRange", valueS, "PatchSettings");
    if (e_autoMacroRange.GetString() == "")
    {
        valueS = "750";
    }
    e_autoMacroRange.SetString(valueS);

И вот сейчас был спорный момент, ибо раз уже замешано ядро - то зачем хранить эти данные в интерфейсе и почему бы не запихивать их куда-то на сервер сайде? Для себя я ответил: чтобы в эдитбоксе выводить актуальную дистанцию и не создавать лишних запросов в БД, а свой ответ Вы можете поискать сами, либо засунуть инфу на серверсайд.

  • Like 4
  • Upvote 2


Рекомендуемые комментарии

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

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