Снятие бафов через Alt+click(double click)
Описание
Нам понадобится
исходники сервера
исходники interface.u с компилятором
Все, что вам нужно, находится в свободном доступе.
Cерверная часть
Сервер в нашем случае ACIS 36x, но подойдет любой (возможно PTS). Все, что требуется, это добавить команду, которая снимет указанный бафф. Чтобы не усложнять пример, давайте обойдемся обходом .
Чтобы снять бафф, более современные клиенты отправляют пакет RequestDispel , поэтому мы будем использовать термин dispel
Сначала добавим метод dispel в L2Character. Как и в более поздних версиях игры, не удаляются эффекты, которые должны остаться после смерти (например, штрафы), дебаффы, танцы и песни:
// L2Character.java public final void dispelSkillEffect ( int skillId, int skillLevel ) { // Find skill with matching ID and level final L2Skill skill = SkillTable. getInstance ( ) . getInfo ( skillId, skillLevel ) ; // Skill wasn't found and can't be dispelled if ( skill == null ) { return ; } // Penalty-like or debuff skill effect can't be dispelled if ( skill.isStayAfterDeath ( ) || skill. isDebuff ( ) ) { return ; } // Stop skill effect by ID _effects. stopSkillEffects ( skill. getId ( ) ) ; }
Теперь добавим обработку в to the runImpl RequestBypassToServer network пакета RequestBypassToServer, который приходит от клиента. Так как метод dispelSkillEffect требует ID навыка и уровень навыка в качестве аргументов, клиент должен передать их в качестве параметров команде dispel :
// 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 , в котором отображаются иконки бафов и дебаффов
Алгоритм:
Слушаем в окне AbnormalStatusWnd событие двойного клика (OnLButtonDblClick)
Определить бафф, на который нажали (через StatusIcon.GetItem)
Определите идентификатор и уровень навыка этого баффа (через GetSkillInfo)
Отправляем запрос на сервер (через RequestBypassToServer или ExecuteCommand)
Вызываем dispelSkillEffect на сервере с полученным ID и уровнем навыка
Событие двойного щелчка левой кнопки мыши OnLButtonDblClick получает в качестве аргументов только координаты щелчка. В то же время StatusIcon.GetItem требует указания строки и столбца ячейки. Соответственно надо определить в какой строке и в какой колонке наших бафов игрок нажал
Поскольку мы знаем, что размер ячейки баффа равен 24 пикселям, а размер ручки, за которую перетаскивается окно, равен 12 пикселям, то вычислить строку и ячейку несложно: достаточно определить координаты окна с бафами вычесть все значения и разделить остаток на размер ячейки. Значения будут правильно округлены при приведении к типу int Во-первых, давайте добавим NSTATUSICON_SIZE
константа, которая описывает размер ячейки баффа, в начало скрипта. Остальные константы разработчика уже описаны:
// AbnormalStatusWnd.uc class AbnormalStatusWnd extends UIScript ; const NSTATUSICON_FRAMESIZE = 12 ; const NSTATUSICON_MAXCOL = 12 ; const NSTATUSICON_SIZE = 24 ; // ...
Теперь в любом месте (например, сразу после функции OnEvent) добавьте обработку события двойного клика:
// 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, скопировать в клиент, запустить игру
Готово!
- 1
Рекомендуемые комментарии
Комментариев нет