Рейтинг темы:
  • 0 Голос(ов) - 0 в среднем
  • 1
  • 2
  • 3
  • 4
  • 5
[share] Skill Handlers
#1
Маленькая шара от меня, так сказать подарочек на Новый Год Smile

Многие наверное видели в сервере от l2jserver так называемые SkillHandlers, позволяющие без особого труда объявлять в датапаке новые обработчики скиллов и вызывать их когда зарегистрированный в них скилл использован.

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

Куда это все применить я пока даже хз - делал реализацию этого всего чисто ради интересу и руководствуясь принципом "потом может пригодится для чего нибудь" Big Grin

Ладно, перейдем к делу, а конкретно к содержимому необходимых классов для ядра.

ISkillHandler.java:
PHP код:
<?php 
package l2p
.gameserver.handler;

import l2p.gameserver.model.L2Character;
import l2p.gameserver.model.L2Effect;
import l2p.gameserver.model.L2Skill;
import l2p.util.GArray;

/**
* Класс для обработки хэндлеров, прикрепляемых к скиллам и их эффектам.
* <br><br>
* Для того, чтобы вызывались методы checkCondition(L2Skill skill, ...), isUseAdditionalCheck(), isOffensive() и useSkill(L2Skill skill, ...),
* необходимо чтобы умение, к которому прикреплен хэндлер, имело тип HANDLER.
* <br><br>
* Для того, чтобы вызывались методы checkCondition(L2Effect effect, ...), onStart(L2Effect effect, ...), onExit(L2Effect effect, ...) и
* onActionTime(L2Effect effect, ...), необходимо чтобы в умении, к которому прикреплен хэндлер, имелся эффект с именем Handler.
*
* @author Gaikotsu
*/
public interface ISkillHandler
{
/**
* Проверка возможности использовать умение на заданную цель.
*
* @param skill - умение
* @param caster - персонаж, кастующий умение
* @param target - цель, на которую используется умение
* @param forceUse - форсированое использование умения (через Ctrl) или обычное
*
* @return - true - умение можно использовать, false - нельзя
* <br><br>
* Если метод isUseAdditionalCheck() хэндлера возвращает true, то после проверок в этом методе, дополнительно будет
* вызван одноименный метод и родительского класса (метод из L2Skill), который проведет дополнительно стандартные проверки на
* возможность использования умения на эту цель.
*/
public boolean checkCondition(L2Skill skill, L2Character caster, L2Character target, boolean forceUse);

/**
* Возвращает признак того, надо ли делать дополнительные проверки возможности использовать умение на заданную цель.
*
* @return - true - проверки проводить надо, false - дополнительные проверки не требуются
*/
public boolean isUseAdditionalCheck();

/**
* Возвращает признак того, является ли умение "плохим" (вызывающим PvP-флаг).
*
* @return - true - умение "плохое", false - умение "хорошее"
*/
public boolean isOffensive();

/**
* Использование умения на список целей.
*
* @param skill - умение
* @param caster - персонаж, кастующий умение
* @param targets - список целей, на которые используется умение
*/
public void useSkill(L2Skill skill, L2Character caster, GArray<L2Character> targets);

/**
* Проверка возможности использовать эффект на заданную цель.
*
* @param effect - эффект
* @param caster - персонаж, накладывающий эффект
* @param target - цель, на которую накладывается эффект
*
* @return - true - эффект можно использовать, false - нельзя
*/
public boolean checkCondition(L2Effect effect, L2Character caster, L2Character target);

/**
* Вызывается при начале работы эффекта.
*
* @param effect - эффект
* @param caster - персонаж, наложивший эффект
* @param target - цель, на которую действует эффект
*/
public void onStart(L2Effect effect, L2Character caster, L2Character target);

/**
* Вызывается при окончании работы эффекта.
*
* @param effect - эффект
* @param caster - персонаж, наложивший эффект
* @param target - цель, на которую действует эффект
*/
public void onExit(L2Effect effect, L2Character caster, L2Character target);

/**
* Вызывается периодически во время действия эффекта.<br>
* Количество и частота вызовов задается в самом описании эффекта в умении (параметры count и time).<br>
* Возвращает возможность дальнейшей работы эффекта.
*
* @param effect - эффект
* @param caster - персонаж, наложивший эффект
* @param target - цель, на которую действует эффект
*
* @return - true - эффект может работать дальше, false - работу эффекта необходимо прервать незамедлительно
*/
public boolean onActionTime(L2Effect effect, L2Character caster, L2Character target);

/**
* Возвращает список умений, на которые зарегистрирован хэндлер.
*
* @return - список умений в виде их идентификаторов
*/
public int[] getSkillIds();
}
SkillHandler.java:
PHP код:
<?php 
package l2p
.gameserver.handler;

import java.util.Map;
import java.util.TreeMap;

public class
SkillHandler
{
private static
SkillHandler _instance;

private
Map<Integer, ISkillHandler> _datatable;

public static
SkillHandler getInstance()
{
if (
_instance == null)
_instance = new SkillHandler();
return
_instance;
}

public
int size()
{
return
_datatable.size();
}

private
SkillHandler()
{
_datatable = new TreeMap<Integer, ISkillHandler>();
}

public
void registerSkillHandler(ISkillHandler handler)
{
int[] ids = handler.getSkillIds();
for (
int element : ids)
_datatable.put(element, handler);
}

public
ISkillHandler getSkillHandler(int skillId)
{
return
_datatable.get(skillId);
}

public
void clear()
{
_datatable.clear();
}
}
Handler.java:
PHP код:
<?php 
package l2p
.gameserver.skills.skillclasses;

import l2p.gameserver.handler.ISkillHandler;
import l2p.gameserver.handler.SkillHandler;
import l2p.gameserver.model.L2Character;
import l2p.gameserver.model.L2Skill;
import l2p.gameserver.templates.StatsSet;
import l2p.util.GArray;

public class
Handler extends L2Skill
{
private
ISkillHandler handler = null;

public
Handler(StatsSet set)
{
super(set);
}

private
ISkillHandler getHandler(int skillId)
{
if (
handler == null)
handler = SkillHandler.getInstance().getSkillHandler(this.getId());

if (
handler == null)
_log.warning("Warning: Not found skill handler for skill " + this.getId() + ", class");

return
handler;
}

@
Override
public boolean checkCondition(L2Character activeChar, L2Character target, boolean forceUse, boolean dontMove, boolean first)
{
if (
getHandler(this.getId()) != null && handler.checkCondition(this, activeChar, target, forceUse))
{
if (
handler.isUseAdditionalCheck())
return
super.checkCondition(activeChar, target, forceUse, dontMove, first);
else
return
true;
}
else
return
false;
}

@
Override
public void useSkill(L2Character activeChar, GArray<L2Character> targets)
{
if (
getHandler(this.getId()) != null)
handler.useSkill(this, activeChar, targets);
}

@
Override
public boolean isOffensive()
{
if (
getHandler(this.getId()) != null)
return
handler.isOffensive();
else
return
super.isOffensive();
}
}
EffectHandler.java:
PHP код:
<?php 
package l2p
.gameserver.skills.effects;

import l2p.gameserver.handler.ISkillHandler;
import l2p.gameserver.handler.SkillHandler;
import l2p.gameserver.model.L2Effect;
import l2p.gameserver.skills.Env;

public final class
EffectHandler extends L2Effect
{
private
ISkillHandler handler = null;

public
EffectHandler(Env env, EffectTemplate template)
{
super(env, template);
handler = SkillHandler.getInstance().getSkillHandler(this.getSkill().getId());

if (
handler == null)
_log.warning("Warning: Not found skill handler for skill " + this.getSkill().getId() + ", effect");
}

@
Override
public boolean checkCondition()
{
if (
handler != null && handler.checkCondition(this, _effector, _effected))
return
super.checkCondition();
else
return
false;
}

@
Override
public void onStart()
{
super.onStart();

if (
handler != null)
handler.onStart(this, _effector, _effected);
}

@
Override
public void onExit()
{
super.onExit();

if (
handler != null)
handler.onExit(this, _effector, _effected);
}

@
Override
public boolean onActionTime()
{
if (
handler != null)
return
handler.onActionTime(this, _effector, _effected);
else
return
false;
}

}
Как зарегистрировать новые класс (HANDLER) и эффект (Handler) скилла в ядре - объяснять уж не буду - это делается легко и просто.

Ну и пример того, как это все работает:

Объявление самого скилла:
PHP код:
<?php 
<skill id="7068" levels="1" name="Test Skill">
<
set name="target" val="TARGET_ONE" />
<
set name="skillType" val="HANDLER" />
<
set name="operateType" val="OP_ACTIVE" />
<for>
<
effect count="5" name="Handler" time="3" val="0" />
</for>
</
skill>
Обработчик методов для этого скилла:
PHP код:
<?php 
package handlers
.skills;

import l2p.extensions.scripts.ScriptFile;
import l2p.gameserver.handler.ISkillHandler;
import l2p.gameserver.handler.SkillHandler;
import l2p.gameserver.model.L2Character;
import l2p.gameserver.model.L2Effect;
import l2p.gameserver.model.L2Skill;
import l2p.util.GArray;

/**
* Пример работы хэндлера, прицепленного к умению.<br>
* Ничего не делает кроме вывода разных сообщений о том, какой из методов хэндлера сработал при работе умения.
* <br><br>
* Для того, чтобы вызывались методы checkCondition(L2Skill skill, ...), isUseAdditionalCheck(), isOffensive() и useSkill(L2Skill skill, ...),
* необходимо чтобы умение, к которому прикреплен хэндлер, имело тип HANDLER.
* <br><br>
* Для того, чтобы вызывались методы checkCondition(L2Effect effect, ...), onStart(L2Effect effect, ...), onExit(L2Effect effect, ...) и
* onActionTime(L2Effect effect, ...), необходимо чтобы в умении, к которому прикреплен хэндлер, имелся эффект с именем Handler.
*
* @author Gaikotsu
*/
public class Sample implements ISkillHandler, ScriptFile
{
private static final
int[] _skillIds = { 7068 };

/**
* Проверка возможности использовать умение на заданную цель.
*
* @param skill - умение
* @param caster - персонаж, кастующий умение
* @param target - цель, на которую используется умение
* @param forceUse - форсированое использование умения (через Ctrl) или обычное
*
* @return - true - умение можно использовать, false - нельзя
* <br><br>
* Если метод isUseAdditionalCheck() хэндлера возвращает true, то после проверок в этом методе, дополнительно будет
* вызван одноименный метод и родительского класса (метод из L2Skill), который проведет дополнительно стандартные проверки на
* возможность использования умения на эту цель.
*/
@Override
public boolean checkCondition(L2Skill skill, L2Character caster, L2Character target, boolean forceUse)
{
if (
caster != null && caster.isPlayer())
caster.getPlayer().sendMessage("skill class: method - checkCondition, caster - " + caster.getName() + ", target - " + target.getName());

return
true;
}

/**
* Возвращает признак того, надо ли делать дополнительные проверки возможности использовать умение на заданную цель.
*
* @return - true - проверки проводить надо, false - дополнительные проверки не требуются
*/
@Override
public boolean isUseAdditionalCheck()
{
return
true;
}

/**
* Возвращает признак того, является ли умение "плохим" (вызывающим PvP-флаг).
*
* @return - true - умение "плохое", false - умение "хорошее"
*/
@Override
public boolean isOffensive()
{
return
false;
}

/**
* Использование умения на список целей.
*
* @param skill - умение
* @param caster - персонаж, кастующий умение
* @param targets - список целей, на которые используется умение
*/
@Override
public void useSkill(L2Skill skill, L2Character caster, GArray<L2Character> targets)
{
if (
caster != null && caster.isPlayer())
{
String _targets = "";

for (
L2Character target : targets)
_targets = _targets + target.getName() + " ";

caster.getPlayer().sendMessage("skill class: method - useSkill, caster - " + caster.getName() + ", target(s) - " + _targets);

for (
L2Character target : targets)
skill.getEffects(caster, target, false, false);
}
}

/**
* Проверка возможности использовать эффект на заданную цель.
*
* @param effect - эффект
* @param caster - персонаж, накладывающий эффект
* @param target - цель, на которую накладывается эффект
*
* @return - true - эффект можно использовать, false - нельзя
*/
@Override
public boolean checkCondition(L2Effect effect, L2Character caster, L2Character target)
{
if (
caster != null && caster.isPlayer())
caster.getPlayer().sendMessage("skill effect: method - checkCondition, caster - " + caster.getName() + ", target - " + target.getName());

return
true;
}

/**
* Вызывается при начале работы эффекта.
*
* @param effect - эффект
* @param caster - персонаж, наложивший эффект
* @param target - цель, на которую действует эффект
*/
@Override
public void onStart(L2Effect effect, L2Character caster, L2Character target)
{
if (
caster != null && caster.isPlayer())
caster.getPlayer().sendMessage("skill effect: method - onStart, caster - " + caster.getName() + ", target - " + target.getName());
}

/**
* Вызывается при окончании работы эффекта.
*
* @param effect - эффект
* @param caster - персонаж, наложивший эффект
* @param target - цель, на которую действует эффект
*/
@Override
public void onExit(L2Effect effect, L2Character caster, L2Character target)
{
if (
caster != null && caster.isPlayer())
caster.getPlayer().sendMessage("skill effect: method - onExit, caster - " + caster.getName() + ", target - " + target.getName());
}

/**
* Вызывается периодически во время действия эффекта.<br>
* Количество и частота вызовов задается в самом описании эффекта в умении (параметры count и time).<br>
* Возвращает возможность дальнейшей работы эффекта.
*
* @param effect - эффект
* @param caster - персонаж, наложивший эффект
* @param target - цель, на которую действует эффект
*
* @return - true - эффект может работать дальше, false - работу эффекта необходимо прервать незамедлительно
*/
@Override
public boolean onActionTime(L2Effect effect, L2Character caster, L2Character target)
{
if (
caster != null && caster.isPlayer())
caster.getPlayer().sendMessage("skill effect: method - onActionTime, caster - " + caster.getName() + ", target - " + target.getName());

return
true;
}

/**
* Возвращает список умений, на которые зарегистрирован хэндлер.
*
* @return - список умений в виде их идентификаторов
*/
@Override
public int[] getSkillIds()
{
return
_skillIds;
}

@
Override
public void onLoad()
{
SkillHandler.getInstance().registerSkillHandler(this);
}

@
Override
public void onReload()
{}

@
Override
public void onShutdown()
{}

}
P.S. С наступающим всех.
Ответ
#2
Экстрасенс? ЧИТАЕШЬ МЫСЛИ?!!! ))))) Была идея, не-добрался пока...
От души!!!
Ответ
#3
Кто может под Ил это?Спасибо.
Ответ
#4
ruslanback;176160 Написал:Кто может под Ил это?Спасибо.
СФ может Smile Не за что.
Ответ
#5
Идея со скиллтайпом и хендлерами к ним в корне не верная, так что в корзину.
Ответ
#6
rage Написал:Идея со скиллтайпом и хендлерами к ним в корне не верная, так что в корзину.

Аргументируйте свою точку зрения.
[Изображение: l2nextgen.gif]
Ответ
#7
Посмотрите офф скиллдату, там нет "типов скилов". Типы скилов придумали в л2ж и пытаются с помощью "типа и таргета" описать то, на что в офф скиллдате 4 параметра.
От сюда и тянется кривая работа почти всех скиллов, тонны говнокогда, багов и ужасной НЕ гибкости в описании скиллов.
Ответ


Возможно похожие темы ...
Тема Автор Ответы Просмотры Последний пост
  [Share] PTS Vanganth - Classic Interlude P110 zoumhs 0 1,469 05-13-2023, 05:04 PM
Последний пост: zoumhs
  Share Gracia Final Off Euro Deazer 424 254,601 07-10-2022, 07:20 PM
Последний пост: JIecTap
  [share] lin][info 2.3 [Lindvior] Gaikotsu 0 1,809 09-22-2017, 08:40 PM
Последний пост: Gaikotsu
  [share] Родильная Комната (Nursery) Gaikotsu 6 2,917 03-23-2017, 11:39 AM
Последний пост: Gaikotsu
  NPC Agument Trade Skill M1xF1ght 0 975 11-17-2015, 05:57 PM
Последний пост: M1xF1ght
  [Share] Silentium Interlude (Last source) Dеmon 77 19,988 12-10-2014, 01:01 AM
Последний пост: kingzor
  Skill power L2J 6 2,343 07-23-2014, 11:18 AM
Последний пост: L2J
  [EPIC SHARE] BBS Advanced Buffer OneThunder 9 3,552 04-28-2014, 11:35 AM
Последний пост: OneThunder
  Lf fandc share iRevive 0 1,209 02-16-2014, 07:19 AM
Последний пост: iRevive
  Parser Skill lCxAxAl 20 5,307 01-05-2014, 12:38 PM
Последний пост: [STIGMATED]

Перейти к форуму:


Пользователи, просматривающие эту тему: 1 Гость(ей)