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

Снятие бафов через 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, скопировать в клиент, запустить игру

Готово!

  • Upvote 1


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

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

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