• Новые темы в этом разделе публикуются автоматически при добавлении файла в менеджер ресурсов.
    Ручное создание новых тем невозможно.

Мануал Добавляем снятие бафов через Alt+click(double click)

interlude

VAAADIM

Заблокирован
Заблокирован
Сообщения
37
Розыгрыши
0
Репутация
42
Реакции
15
Баллы
188
Обратите внимание, что данный пользователь заблокирован! Не совершайте с ним никаких сделок! Перейдите в его профиль, чтобы узнать причину блокировки.
Нам понадобится
  • исходники сервера
  • исходники interface.u с компилятором

Все, что вам нужно, находится в свободном доступе.
Cерверная часть

Сервер в нашем случае ACIS 36x, но подойдет любой (возможно PTS). Все, что требуется, это добавить команду, которая снимет указанный бафф. Чтобы не усложнять пример, давайте обойдемся обходом .

Чтобы снять бафф, более современные клиенты отправляют пакет RequestDispel , поэтому мы будем использовать термин dispel

Сначала добавим метод dispel в L2Character. Как и в более поздних версиях игры, не удаляются эффекты, которые должны остаться после смерти (например, штрафы), дебаффы, танцы и песни:
Java:
// L2Character.java
 
public  final  void dispelSkillEffect ( int skillId, int skillLevel )  {
    // Найти скилл с подходящим ID и уровнем
    final L2Skill skill = SkillTable. getInstance ( ) . getInfo ( skillId, skillLevel ) ;
    // Skill не найден и не может быть отменён
    if  ( skill ==  null )
    {
        return ;
    }
    // Пенальти и дебафы не могут быть отменены
    if  ( skill.isStayAfterDeath ( )  || skill. isDebuff ( ) )
    {
        return ;
    }
   
    // Сбрасывать с персонажа эфект скила с ид
    _effects. stopSkillEffects ( skill
Теперь добавим обработку в to the runImpl RequestBypassToServer network пакета RequestBypassToServer, который приходит от клиента. Так как метод dispelSkillEffect требует ID навыка и уровень навыка в качестве аргументов, клиент должен передать их в качестве параметров команде dispel :
Java:
// RequestBypassToServer.java
 
// Usage: _dispel:<int:skill_id>,<int:skill_level>
// Example: _dispel:313,8
else  if  ( _command. startsWith ( "_dispel" ) )
{
   
    String params = _command. substring ( _command. indexOf ( ":" )  +  1 ) ;
    // Split params into tokens
    StringTokenizer st =  new  StringTokenizer ( params, "," ) ;
    // Get skill ID from first token
    intid =  Integer . parseInt ( st.nextToken ( ) ) ;
    activeChar. dispelSkillEffect ( id, level ) ; }
Пример вызова: _dispel:313,8 I

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

Сторона клиента

К сожалению, простого способа отслеживания Alt+Click в клиенте Interlude нет, поэтому используем обычный двойной клик левой кнопки мыши для снятия баффа . Событие будет обрабатываться окном AbnormalStatusWnd , в котором отображаются иконки бафов и дебаффов

Алгоритм:

  1. Слушаем в окне AbnormalStatusWnd событие двойного клика (OnLButtonDblClick)
  2. Определить бафф, на который нажали (через StatusIcon.GetItem)
  3. Определите идентификатор и уровень навыка этого баффа (через GetSkillInfo)
  4. Отправляем запрос на сервер (через RequestBypassToServer или ExecuteCommand)
  5. Вызываем dispelSkillEffect на сервере с полученным ID и уровнем навыка

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

Поскольку мы знаем, что размер ячейки баффа равен 24 пикселям, а размер ручки, за которую перетаскивается окно, равен 12 пикселям, то вычислить строку и ячейку несложно: достаточно определить координаты окна с бафами вычесть все значения и разделить остаток на размер ячейки. Значения будут правильно округлены при приведении к типу int Во-первых, давайте добавим NSTATUSICON_SIZE

константа, которая описывает размер ячейки баффа, в начало скрипта. Остальные константы разработчика уже описаны:
Java:
// AbnormalStatusWnd.uc
 
class AbnormalStatusWnd extends UIScript ;
 
const NSTATUSICON_FRAMESIZE =  12 ;
const NSTATUSICON_MAXCOL =  12 ;
const NSTATUSICON_SIZE =  24 ;
 
// ...
Теперь в любом месте (например, сразу после функции OnEvent) добавьте обработку события двойного клика:
Java:
// AbnormalStatusWnd.uc
 
function OnLButtonDblClick ( int X ,  int Y )  {
    local Rect windowBounds ;
    local int targetRow ;
    local int targetCol ;
 
    local StatusIconInfo info ;
    local SkillInfo skillInfo ;
 
    // Find window position
    windowBounds = Me. GetRect ( ) ;
 
    // Process clicks outside of window frame only
    if  ( X >  ( windowBounds. nX +  NSTATUSICON_FRAMESIZE ) ) { 
        targetRow =  ( Y - windowBounds. nY )  / NSTATUSICON_SIZE ;
        targetCol =  ( X - windowBounds. nX  - NSTATUSICON_FRAMESIZE )  / NSTATUSICON_SIZE ;
 
      
        StatusIcon. GetItem ( targetRow , targetCol , info ) ;
 
      
        if  ( GetSkillInfo ( info. ClassID , info. Level , skillInfo ) )  {
            // Request server to stop skill effect
            // Usage: _dispel:<int:skill_id>,<int :skill_level>
            // Example: _dispel:313,8
            RequestBypassToServer ( "_dispel:" $ string ( skillInfo. SkillID ) $ "," $ string ( skillInfo. SkillLevel ) ) ) ;
        }
    }
}
Скомпилировать interface.u, скопировать в клиент, запустить игру

Готово!
 

Обратите внимание, что данный пользователь заблокирован! Не совершайте с ним никаких сделок! Перейдите в его профиль, чтобы узнать причину блокировки.
Код:
// L2Character.java
 
public  final  void dispelSkillEffect ( int skillId, int skillLevel )  {
    // Найти скилл с подходящим ID и уровнем
    final L2Skill skill = SkillTable. getInstance ( ) . getInfo ( skillId, skillLevel ) ;
    // Skill не найден и не может быть отменён
    if  ( skill ==  null )
    {
        return ;
    }
    // Пенальти и дебафы не могут быть отменены
    if  ( skill.isStayAfterDeath ( )  || skill. isDebuff ( ) )
    {
        return ;
    }
  
    // Сбрасывать с персонажа эфект скила с ид
    _effects. stopSkillEffects ( skill
Java:
// L2Character.java
 
public  final  void dispelSkillEffect ( int skillId, int skillLevel )  {
   
    final L2Skill skill = SkillTable. getInstance ( ) . getInfo ( skillId, skillLevel ) ;
  
    if  ( skill ==  null )
    {
        return ;
    }
  
    if  ( skill.isStayAfterDeath ( )  || skill. isDebuff ( ) )
    {
        return ;
    }
    
   
    _effects. stopSkillEffects ( skill. getId ( ) ) ;
}
 
К сожалению, простого способа отслеживания Alt+Click в клиенте Interlude нет, поэтому используем обычный двойной клик левой кнопки мыши для снятия баффа . Событие будет обрабатываться окном AbnormalStatusWnd , в котором отображаются иконки бафов и дебаффов
У говнолюда точно есть OnKeyDown\Up, что как бы намекает, что alt+click всё таки сделать можно, если немного постараться.

C#:
function OnKeyDown(EInputKey nKey)
{
    if (nKey == IK_Alt )
        bAltClicked = true;
}
function OnKeyUp(EInputKey nKey)
{
    if (nKey == IK_Alt )
        bAltClicked = false;
}

Что касается StatusIconCtrl - а разве хендлер OnClickItem не принимает нажатия в этот элемент? Если да, то это немного ослабит вашу жажду математики, т.к. индекс тут возвращается в аргументе и ничего считать не надо.
C#:
event OnClickItem(string strID, int Index);

P.S. Я не знаю точно, как он работает в ИТ, но в хрониках выше клики в StatusIcon принимает OnClickItem. Возможно это было сделано как раз для alt+click баффов и в ИТ никакого листенера на StatusIcon нет.
 
Последнее редактирование:
  • Мне нравится
Реакции: kick
У говнолюда точно есть OnKeyDown\Up, что как бы намекает, что alt+click всё таки сделать можно, если немного постараться.

C#:
function OnKeyDown(EInputKey nKey)
{
    if (nKey == IK_Alt )
        bAltClicked = true;
}
function OnKeyUp(EInputKey nKey)
{
    if (nKey == IK_Alt )
        bAltClicked = false;
}

Что касается StatusIconCtrl - а разве хендлер OnClickItem не принимает нажатия в этот элемент? Если да, то это немного ослабит вашу жажду математики, т.к. индекс тут возвращается в аргументе и ничего считать не надо.
C#:
event OnClickItem(string strID, int Index);

P.S. Я не знаю точно, как он работает в ИТ, но в хрониках выше клики в StatusIcon принимает OnClickItem. Возможно это было сделано как раз для alt+click баффов и в ИТ никакого листенера на StatusIcon нет.
Не помню точно, но вроде есть и IsKeyDown, что автоматически избавляет от костылей с OnKeyDown и OnKeyUp
 
  • Мне нравится
Реакции: kick
Не помню точно, но вроде есть и IsKeyDown, что автоматически избавляет от костылей с OnKeyDown и OnKeyUp
Ну это так, костыли для костылей, старый добрый интерлюдик.

P.S. На месте ТСа я бы задумался не над костылингом синего трупа, а над подъёмом пакетки до каких то более или менее адекватных клиентов, которые уже имеют весь необходимый функционал, типа RequestDispel. Под адекватными я имею ввиду 152 протокол и выше.

Это конечно предложении из серии забраться на Эверест, в то время как ТС просто предложил сходить в ларёк за сигаретами, но тем не менее.
 
  • Мне нравится
Реакции: kick
Обратите внимание, что данный пользователь заблокирован! Не совершайте с ним никаких сделок! Перейдите в его профиль, чтобы узнать причину блокировки.
Не помню точно, но вроде есть и IsKeyDown, что автоматически избавляет от костылей с OnKeyDown и OnKeyUp
Сам по себе интрелюдик костыль для ностальгирующих по старой л2)
В остальном же, возможно и есть более рациональные варианты сделать и оптимизировать, я же общую схему для всех предложил а дальше - в силу своих сил и умений пускай разбираются и шаманят)
 
1667203826358.png

Что за обход? Гугл транслит что ли? )

P.S.: интересно, сколько раз еще копи-пастнут этот пост, до того как удалят лишнюю скобку? :unsure:
Код:
            RequestBypassToServer ( "_dispel:" $ string ( skillInfo. SkillID ) $ "," $ string ( skillInfo. SkillLevel ) ) ) ;
 
Ну это так, костыли для костылей, старый добрый интерлюдик.

P.S. На месте ТСа я бы задумался не над костылингом синего трупа, а над подъёмом пакетки до каких то более или менее адекватных клиентов, которые уже имеют весь необходимый функционал, типа RequestDispel. Под адекватными я имею ввиду 152 протокол и выше.

Это конечно предложении из серии забраться на Эверест, в то время как ТС просто предложил сходить в ларёк за сигаретами, но тем не менее.
Я вот взял 362 и копаю как раз по реализациям которых нет, олли 3 на 3, мировая торговля, сундук

и вот нет проблем с тем какие пакеты прилетают от клиента, у меня вопрос как понять чего ожидает клиент получить для правильной отправки данных... не подскажешь в какую сторону копать для этого, от куда другие берут информацию для этого? спасибо =)
 
this work for java or l2off?
 
Нужно было указать что скопиравно это все со шмакси
 
  • Клоун
Реакции: Die
Посмотреть вложение 46097

Что за обход? Гугл транслит что ли? )

P.S.: интересно, сколько раз еще копи-пастнут этот пост, до того как удалят лишнюю скобку? :unsure:
Код:
            RequestBypassToServer ( "_dispel:" $ string ( skillInfo. SkillID ) $ "," $ string ( skillInfo. SkillLevel ) ) ) ;
Насколько оправдано в UC приводить переменные к стринг-типу, если вначале уже была использована текстовая строка? По моему компилятору наплевать на такие кейзы.

Следую аналогичной логике, можно ещё более кислотные конструкции строить -
C#:
local float f;

f = 25.4;
RequestBypassToServer ( "shas int otpravim, eba: " $ string(int(f)) ) ;
 
Насколько оправдано в UC приводить переменные к стринг-типу, если вначале уже была использована текстовая строка? По моему компилятору наплевать на такие кейзы.

Следую аналогичной логике, можно ещё более кислотные конструкции строить -
C#:
local float f;

f = 25.4;
RequestBypassToServer ( "shas int otpravim, eba: " $ string(int(f)) ) ;
компилятор автоматически добавит вызов этого приведения, если потом взглянешь на декомпил, сам в этом убедишься, по этому по сути не имеет значения, делать это самому руками или же компилятор добавит это самостоятельно
 
Совсем дурак чтоли? Это скопировано с зоны, откуда шмакси забрало) шмакси говорит юморист))
Сорян чуть подобосрался, ТС и на шмакси данный мануал писал
 
Под адекватными я имею ввиду 152 протокол и выше.
Чисто формально, пакет появился в GP1, поэтому наверняка можно апнуть и чуть-чуть ниже. (например до 83). А интерфейс всегда можно кастрировать :)
 
Назад
Сверху Снизу