Форум администраторов игровых серверов

Форум администраторов игровых серверов (https://forum.zone-game.info/TT.php)
-   Lineage II (https://forum.zone-game.info/forumdisplay.php?f=34)
-   -   [share] Skill Handlers (https://forum.zone-game.info/showthread.php?t=17258)

Gaikotsu 22.12.2011 21:28

[share] Skill Handlers
 
Маленькая шара от меня, так сказать подарочек на Новый Год :)

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

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

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

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

ISkillHandler.java:
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 skillL2Character casterL2Character targetboolean forceUse);

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

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

    
/**
     * Использование умения на список целей.
     * 
     * @param skill        - умение
     * @param caster    - персонаж, кастующий умение
     * @param targets    - список целей, на которые используется умение
     */
    
public void useSkill(L2Skill skillL2Character casterGArray<L2Charactertargets);
    
    
/**
     * Проверка возможности использовать эффект на заданную цель.
     * 
     * @param effect    - эффект
     * @param caster    - персонаж, накладывающий эффект
     * @param target    - цель, на которую накладывается эффект
     * 
     * @return        - true - эффект можно использовать, false - нельзя
     */
    
public boolean checkCondition(L2Effect effectL2Character casterL2Character target);

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


SkillHandler.java:
PHP код:

package l2p.gameserver.handler;

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

public class 
SkillHandler
{
    private static 
SkillHandler _instance;

    private 
Map<IntegerISkillHandler_datatable;

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

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

    private 
SkillHandler()
    {
        
_datatable = new TreeMap<IntegerISkillHandler>();
    }

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

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

    public 
void clear()
    {
        
_datatable.clear();
    }


Handler.java:
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 activeCharL2Character targetboolean forceUseboolean dontMoveboolean first)
    {
        if (
getHandler(this.getId()) != null && handler.checkCondition(thisactiveChartargetforceUse))
        {
            if (
handler.isUseAdditionalCheck())
                return 
super.checkCondition(activeChartargetforceUsedontMovefirst);
            else
                return 
true;
        }
        else
            return 
false;
    }

    @
Override
    
public void useSkill(L2Character activeCharGArray<L2Charactertargets)
    {
        if (
getHandler(this.getId()) != null)
            
handler.useSkill(thisactiveChartargets);
    }
    
    @
Override
    
public boolean isOffensive()
    {
        if (
getHandler(this.getId()) != null)
            return 
handler.isOffensive();
        else
            return 
super.isOffensive();
    }


EffectHandler.java:
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 envEffectTemplate template)
    {
        
super(envtemplate);
        
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 код:

    <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 код:

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 ISkillHandlerScriptFile
{
    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 skillL2Character casterL2Character targetboolean 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 skillL2Character casterGArray<L2Charactertargets)
    {
        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(castertargetfalsefalse);
        }
    }

    
/**
     * Проверка возможности использовать эффект на заданную цель.
     * 
     * @param effect    - эффект
     * @param caster    - персонаж, накладывающий эффект
     * @param target    - цель, на которую накладывается эффект
     * 
     * @return        - true - эффект можно использовать, false - нельзя
     */
    
@Override
    
public boolean checkCondition(L2Effect effectL2Character casterL2Character 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 effectL2Character casterL2Character 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 effectL2Character casterL2Character 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 effectL2Character casterL2Character 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. С наступающим всех.

KilRoy 22.12.2011 22:30

Re: [share] Skill Handlers
 
Экстрасенс? ЧИТАЕШЬ МЫСЛИ?!!! ))))) Была идея, не-добрался пока...
От души!!!

ruslanback 06.04.2012 23:54

Re: [share] Skill Handlers
 
Кто может под Ил это?Спасибо.

KilRoy 07.04.2012 00:11

Re: [share] Skill Handlers
 
Цитата:

Сообщение от ruslanback (Сообщение 176160)
Кто может под Ил это?Спасибо.

СФ может :) Не за что.

rage 10.04.2012 09:07

Re: [share] Skill Handlers
 
Идея со скиллтайпом и хендлерами к ним в корне не верная, так что в корзину.

bloodshed 10.04.2012 09:37

Re: [share] Skill Handlers
 
Цитата:

Сообщение от rage (Сообщение 177122)
Идея со скиллтайпом и хендлерами к ним в корне не верная, так что в корзину.

Аргументируйте свою точку зрения.

rage 10.04.2012 11:05

Re: [share] Skill Handlers
 
Посмотрите офф скиллдату, там нет "типов скилов". Типы скилов придумали в л2ж и пытаются с помощью "типа и таргета" описать то, на что в офф скиллдате 4 параметра.
От сюда и тянется кривая работа почти всех скиллов, тонны говнокогда, багов и ужасной НЕ гибкости в описании скиллов.


Текущее время: 22:54. Часовой пояс GMT +3.

Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot