Advertisement
GOODPower

Untitled

May 28th, 2014
217
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 17.11 KB | None | 0 0
  1. package l2p.gameserver.model;
  2.  
  3. import java.util.concurrent.Future;
  4. import java.util.concurrent.atomic.AtomicInteger;
  5. import l2p.commons.threading.RunnableImpl;
  6. import l2p.gameserver.Config;
  7. import l2p.gameserver.listener.actor.OnAttackListener;
  8. import l2p.gameserver.listener.actor.OnMagicUseListener;
  9. import l2p.gameserver.handler.bbs.impl.bbsbuffer.BBSBuffer;
  10. import l2p.gameserver.handler.bbs.impl.bbsbuffer.BBSBufferConfig;
  11. import l2p.gameserver.serverpackets.AbnormalStatusUpdate;
  12. import l2p.gameserver.serverpackets.ExOlympiadSpelledInfo;
  13. import l2p.gameserver.serverpackets.PartySpelled;
  14. import l2p.gameserver.serverpackets.ShortBuffStatusUpdate;
  15. import l2p.gameserver.serverpackets.SystemMessage;
  16. import l2p.gameserver.serverpackets.components.SystemMsg;
  17. import l2p.gameserver.skills.AbnormalEffect;
  18. import l2p.gameserver.skills.EffectType;
  19. import l2p.gameserver.skills.effects.EffectTemplate;
  20. import l2p.gameserver.stats.Env;
  21. import l2p.gameserver.stats.funcs.Func;
  22. import l2p.gameserver.stats.funcs.FuncOwner;
  23. import l2p.gameserver.tables.SkillTable;
  24. import l2p.gameserver.taskmanager.EffectTaskManager;
  25. import org.slf4j.Logger;
  26. import org.slf4j.LoggerFactory;
  27.  
  28. public abstract class Effect extends RunnableImpl implements Comparable<Effect>, FuncOwner
  29. {
  30.     protected static final Logger _log = LoggerFactory.getLogger(Effect.class);
  31.  
  32.     public final static Effect[] EMPTY_L2EFFECT_ARRAY = new Effect[0];
  33.  
  34.     //Состояние, при котором работает задача запланированного эффекта
  35.     public static int SUSPENDED = -1;
  36.  
  37.     public static int STARTING = 0;
  38.     public static int STARTED = 1;
  39.     public static int ACTING = 2;
  40.     public static int FINISHING = 3;
  41.     public static int FINISHED = 4;
  42.  
  43.     /** Накладывающий эффект */
  44.     protected final Creature _effector;
  45.     /** Тот, на кого накладывают эффект */
  46.     protected final Creature _effected;
  47.  
  48.     protected final Skill _skill;
  49.     protected final int _displayId;
  50.     protected final int _displayLevel;
  51.  
  52.     // the value of an update
  53.     private final double _value;
  54.  
  55.     // the current state
  56.     private final AtomicInteger _state;
  57.  
  58.     // counter
  59.     private int _count;
  60.  
  61.     // period, milliseconds
  62.     private long _period;
  63.     private long _startTimeMillis;
  64.     private long _duration;
  65.  
  66.     private boolean _inUse = false;
  67.     private Effect _next = null;
  68.     private boolean _active = false;
  69.  
  70.     protected final EffectTemplate _template;
  71.  
  72.     private Future<?> _effectTask;
  73.  
  74.     protected Effect(Env env, EffectTemplate template)
  75.     {
  76.         _skill = env.skill;
  77.         _effector = env.character;
  78.         _effected = env.target;
  79.  
  80.         _template = template;
  81.         _value = template._value;
  82.         _count = template.getCount();
  83.         _period = template.getPeriod();
  84.  
  85.         _duration = _period * _count;
  86.  
  87.         _displayId = template._displayId != 0 ? template._displayId : _skill.getDisplayId();
  88.         _displayLevel = template._displayLevel != 0 ? template._displayLevel : _skill.getDisplayLevel();
  89.  
  90.         _state = new AtomicInteger(STARTING);
  91.     }
  92.  
  93.     public long getPeriod()
  94.     {
  95.         return _period;
  96.     }
  97.  
  98.     public void setPeriod(long time)
  99.     {
  100.         _period = time;
  101.         _duration = _period * _count;
  102.     }
  103.  
  104.     public int getCount()
  105.     {
  106.         return _count;
  107.     }
  108.  
  109.     public void setCount(int count)
  110.     {
  111.         _count = count;
  112.         _duration = _period * _count;
  113.     }
  114.  
  115.     public boolean isOneTime()
  116.     {
  117.         return _period == 0;
  118.     }
  119.  
  120.     /**
  121.      * Возвращает время старта эффекта, если время не установлено, возвращается текущее
  122.      */
  123.     public long getStartTime()
  124.     {
  125.         if(_startTimeMillis == 0L)
  126.             return System.currentTimeMillis();
  127.         return _startTimeMillis;
  128.     }
  129.  
  130.     /** Возвращает общее время действия эффекта в миллисекундах. */
  131.     public long getTime()
  132.     {
  133.         return System.currentTimeMillis() - getStartTime();
  134.     }
  135.  
  136.     /** Возвращает длительность эффекта в миллисекундах. */
  137.     public long getDuration()
  138.     {
  139.         return _duration;
  140.     }
  141.  
  142.     /** Возвращает оставшееся время в секундах. */
  143.     public int getTimeLeft()
  144.     {
  145.         return (int) ((getDuration() - getTime()) / 1000L);
  146.     }
  147.  
  148.     /** Возвращает true, если осталось время для действия эффекта */
  149.     public boolean isTimeLeft()
  150.     {
  151.         return getDuration() - getTime() > 0L;
  152.     }
  153.  
  154.     public boolean isInUse()
  155.     {
  156.         return _inUse;
  157.     }
  158.  
  159.     public void setInUse(boolean inUse)
  160.     {
  161.         _inUse = inUse;
  162.     }
  163.  
  164.     public boolean isActive()
  165.     {
  166.         return _active;
  167.     }
  168.  
  169.     /**
  170.      * Для неактивных эфектов не вызывается onActionTime.
  171.      */
  172.     public void setActive(boolean set)
  173.     {
  174.         _active = set;
  175.     }
  176.  
  177.     public EffectTemplate getTemplate()
  178.     {
  179.         return _template;
  180.     }
  181.  
  182.     public String getStackType()
  183.     {
  184.         return getTemplate()._stackType;
  185.     }
  186.  
  187.     public String getStackType2()
  188.     {
  189.         return getTemplate()._stackType2;
  190.     }
  191.  
  192.     public boolean checkStackType(String param)
  193.     {
  194.         return getStackType().equalsIgnoreCase(param) || getStackType2().equalsIgnoreCase(param);
  195.     }
  196.  
  197.     public boolean checkStackType(Effect param)
  198.     {
  199.         return checkStackType(param.getStackType()) || checkStackType(param.getStackType2());
  200.     }
  201.  
  202.     public int getStackOrder()
  203.     {
  204.         return getTemplate()._stackOrder;
  205.     }
  206.  
  207.     public Skill getSkill()
  208.     {
  209.         return _skill;
  210.     }
  211.  
  212.     public Creature getEffector()
  213.     {
  214.         return _effector;
  215.     }
  216.  
  217.     public Creature getEffected()
  218.     {
  219.         return _effected;
  220.     }
  221.  
  222.     public double calc()
  223.     {
  224.         return _value;
  225.     }
  226.  
  227.     public boolean isEnded()
  228.     {
  229.         return isFinished() || isFinishing();
  230.     }
  231.  
  232.     public boolean isFinishing()
  233.     {
  234.         return getState() == FINISHING;
  235.     }
  236.  
  237.     public boolean isFinished()
  238.     {
  239.         return getState() == FINISHED;
  240.     }
  241.  
  242.     private int getState()
  243.     {
  244.         return _state.get();
  245.     }
  246.  
  247.     private boolean setState(int oldState, int newState)
  248.     {
  249.         return _state.compareAndSet(oldState, newState);
  250.     }
  251.  
  252.     private ActionDispelListener _listener;
  253.  
  254.     private class ActionDispelListener implements OnAttackListener, OnMagicUseListener
  255.     {
  256.         @Override
  257.         public void onMagicUse(Creature actor, Skill skill, Creature target, boolean alt)
  258.         {
  259.             exit();
  260.         }
  261.  
  262.         @Override
  263.         public void onAttack(Creature actor, Creature target)
  264.         {
  265.             exit();
  266.         }
  267.     }
  268.  
  269.     public boolean checkCondition()
  270.     {
  271.         return true;
  272.     }
  273.  
  274.     /** Notify started */
  275.     protected void onStart()
  276.     {
  277.         getEffected().addStatFuncs(getStatFuncs());
  278.         getEffected().addTriggers(getTemplate());
  279.         if(getTemplate()._abnormalEffect != AbnormalEffect.NULL)
  280.             getEffected().startAbnormalEffect(getTemplate()._abnormalEffect);
  281.         else if(getEffectType().getAbnormal() != null)
  282.             getEffected().startAbnormalEffect(getEffectType().getAbnormal());
  283.         if(getTemplate()._abnormalEffect2 != AbnormalEffect.NULL)
  284.             getEffected().startAbnormalEffect(getTemplate()._abnormalEffect2);
  285.         if(getTemplate()._abnormalEffect3 != AbnormalEffect.NULL)
  286.             getEffected().startAbnormalEffect(getTemplate()._abnormalEffect3);
  287.         if(_template._cancelOnAction)
  288.             getEffected().addListener(_listener = new ActionDispelListener());
  289.         if(getEffected().isPlayer() && !getSkill().canUseTeleport())
  290.             getEffected().getPlayer().getPlayerAccess().UseTeleport = false;
  291.     }
  292.  
  293.     /** Return true for continuation of this effect */
  294.     protected abstract boolean onActionTime();
  295.  
  296.     /**
  297.      * Cancel the effect in the the abnormal effect map of the effected L2Character.<BR><BR>
  298.      */
  299.     protected void onExit()
  300.     {
  301.         getEffected().removeStatsOwner(this);
  302.         getEffected().removeTriggers(getTemplate());
  303.         if(getTemplate()._abnormalEffect != AbnormalEffect.NULL)
  304.             getEffected().stopAbnormalEffect(getTemplate()._abnormalEffect);
  305.         else if(getEffectType().getAbnormal() != null)
  306.             getEffected().stopAbnormalEffect(getEffectType().getAbnormal());
  307.         if(getTemplate()._abnormalEffect2 != AbnormalEffect.NULL)
  308.             getEffected().stopAbnormalEffect(getTemplate()._abnormalEffect2);
  309.         if(getTemplate()._abnormalEffect3 != AbnormalEffect.NULL)
  310.             getEffected().stopAbnormalEffect(getTemplate()._abnormalEffect3);
  311.         if(_template._cancelOnAction)
  312.             getEffected().removeListener(_listener);
  313.         if(getEffected().isPlayer() && getStackType().equals(EffectTemplate.HP_RECOVER_CAST))
  314.             getEffected().sendPacket(new ShortBuffStatusUpdate());
  315.         if(getEffected().isPlayer() && !getSkill().canUseTeleport() && !getEffected().getPlayer().getPlayerAccess().UseTeleport)
  316.             getEffected().getPlayer().getPlayerAccess().UseTeleport = true;
  317.        
  318.         // BBS Buffer by Masterio
  319.         if(BBSBufferConfig.AUTOREBUFF_ENABLED)
  320.         {
  321.             if(getEffected() instanceof Player)
  322.             {
  323.                 BBSBuffer BB = ((Player) getEffected())._bbsbuffer;
  324.                
  325.                 if(!BB.isRebuffPlayerTaskExecute() && BB.getRebuffPlayerSchemeId() > 0 && BB.isSkillInSchemeExists(getSkill().getId(), true))
  326.                     BB.startRebuffPlayerTaskSchedule();
  327.             }
  328.             else if(getEffected() instanceof Summon)
  329.             {
  330.                 BBSBuffer BB = getEffected().getPlayer()._bbsbuffer;
  331.                
  332.                 if(!BB.isRebuffSummonTaskExecute() && BB.getRebuffSummonSchemeId() > 0 && BB.isSkillInSchemeExists(getSkill().getId(), false))
  333.                     BB.startRebuffSummonTaskSchedule();
  334.             }
  335.         }
  336.     }
  337.  
  338.     private void stopEffectTask()
  339.     {
  340.         if(_effectTask != null)
  341.             _effectTask.cancel(false);
  342.     }
  343.  
  344.     private void startEffectTask()
  345.     {
  346.         if(_effectTask == null)
  347.         {
  348.             _startTimeMillis = System.currentTimeMillis();
  349.             _effectTask = EffectTaskManager.getInstance().scheduleAtFixedRate(this, _period, _period);
  350.         }
  351.     }
  352.  
  353.     /**
  354.      * Добавляет эффект в список эффектов, в случае успешности вызывается метод start
  355.      */
  356.     public final void schedule()
  357.     {
  358.         Creature effected = getEffected();
  359.         if(effected == null)
  360.             return;
  361.  
  362.         if(!checkCondition())
  363.             return;
  364.  
  365.         getEffected().getEffectList().addEffect(this);
  366.     }
  367.  
  368.     /**
  369.      * Переводит эффект в "фоновый" режим, эффект может быть запущен методом schedule
  370.      */
  371.     private final void suspend()
  372.     {
  373.         // Эффект создан, запускаем задачу в фоне
  374.         if(setState(STARTING, SUSPENDED))
  375.             startEffectTask();
  376.         else if(setState(STARTED, SUSPENDED) || setState(ACTING, SUSPENDED))
  377.         {
  378.             synchronized (this)
  379.             {
  380.                 if(isInUse())
  381.                 {
  382.                     setInUse(false);
  383.                     setActive(false);
  384.                     onExit();
  385.                 }
  386.             }
  387.             getEffected().getEffectList().removeEffect(this);
  388.         }
  389.     }
  390.  
  391.     /**
  392.      * Запускает задачу эффекта, в случае если эффект успешно добавлен в список
  393.      */
  394.     public final void start()
  395.     {
  396.         if(setState(STARTING, STARTED))
  397.         {
  398.             synchronized (this)
  399.             {
  400.                 if(isInUse())
  401.                 {
  402.                     setActive(true);
  403.                     onStart();
  404.                     startEffectTask();
  405.                 }
  406.             }
  407.         }
  408.  
  409.         run();
  410.     }
  411.  
  412.     @Override
  413.     public final void runImpl() throws Exception
  414.     {
  415.         if(setState(STARTED, ACTING))
  416.         {
  417.             // Отображать сообщение только для первого эффекта скилла
  418.             if(!getSkill().isHideStartMessage() && getEffected().getEffectList().getEffectsCountForSkill(getSkill().getId()) == 1)
  419.                 getEffected().sendPacket(new SystemMessage(SystemMsg.S1_EFFECT_CAN_BE_FELT).addSkillName(_displayId, _displayLevel));
  420.  
  421.             return;
  422.         }
  423.  
  424.         if(getState() == SUSPENDED)
  425.         {
  426.             if(isTimeLeft())
  427.             {
  428.                 _count--;
  429.                 if(isTimeLeft())
  430.                     return;
  431.             }
  432.  
  433.             exit();
  434.             return;
  435.         }
  436.  
  437.         if(getState() == ACTING)
  438.             if(isTimeLeft())
  439.             {
  440.                 _count--;
  441.                 if((!isActive() || onActionTime()) && isTimeLeft())
  442.                     return;
  443.             }
  444.  
  445.         if(setState(ACTING, FINISHING))
  446.             setInUse(false);
  447.  
  448.         if(setState(FINISHING, FINISHED))
  449.         {
  450.             synchronized (this)
  451.             {
  452.                 setActive(false);
  453.                 stopEffectTask();
  454.                 onExit();
  455.             }
  456.  
  457.             // Добавляем следующий запланированный эффект
  458.             Effect next = getNext();
  459.             if(next != null)
  460.                 if(next.setState(SUSPENDED, STARTING))
  461.                     next.schedule();
  462.  
  463.             if(getSkill().getDelayedEffect() > 0)
  464.                 SkillTable.getInstance().getInfo(getSkill().getDelayedEffect(), 1).getEffects(_effector, _effected, false, false);
  465.  
  466.             boolean msg = !isHidden() && getEffected().getEffectList().getEffectsCountForSkill(getSkill().getId()) == 1;
  467.  
  468.             getEffected().getEffectList().removeEffect(this);
  469.  
  470.             // Отображать сообщение только для последнего оставшегося эффекта скилла
  471.             if(msg)
  472.                 getEffected().sendPacket(new SystemMessage(SystemMsg.S1_HAS_WORN_OFF).addSkillName(_displayId, _displayLevel));
  473.         }
  474.     }
  475.  
  476.     /**
  477.      * Завершает эффект и все связанные, удаляет эффект из списка эффектов
  478.      */
  479.     public final void exit()
  480.     {
  481.         Effect next = getNext();
  482.         if(next != null)
  483.             next.exit();
  484.         removeNext();
  485.  
  486.         //Эффект запланирован на запуск, удаляем
  487.         if(setState(STARTING, FINISHED))
  488.             getEffected().getEffectList().removeEffect(this);
  489.         //Эффект работает в "фоне", останавливаем задачу в планировщике
  490.         else if(setState(SUSPENDED, FINISHED))
  491.             stopEffectTask();
  492.         else if(setState(STARTED, FINISHED) || setState(ACTING, FINISHED))
  493.         {
  494.             synchronized (this)
  495.             {
  496.                 if(isInUse())
  497.                 {
  498.                     setInUse(false);
  499.                     setActive(false);
  500.                     stopEffectTask();
  501.                     onExit();
  502.                 }
  503.             }
  504.             getEffected().getEffectList().removeEffect(this);
  505.         }
  506.     }
  507.  
  508.     /**
  509.      * Поставить в очередь эффект
  510.      * @param e
  511.      * @return true, если эффект поставлен в очередь
  512.      */
  513.     private boolean scheduleNext(Effect e)
  514.     {
  515.         if(e == null || e.isEnded())
  516.             return false;
  517.  
  518.         Effect next = getNext();
  519.         if(next != null && !next.maybeScheduleNext(e))
  520.             return false;
  521.  
  522.         _next = e;
  523.  
  524.         return true;
  525.     }
  526.  
  527.     public Effect getNext()
  528.     {
  529.         return _next;
  530.     }
  531.  
  532.     private void removeNext()
  533.     {
  534.         _next = null;
  535.     }
  536.  
  537.     /**
  538.      * @return false - игнорировать новый эффект, true - использовать новый эффект
  539.      */
  540.     public boolean maybeScheduleNext(Effect newEffect)
  541.     {
  542.         if(newEffect.getStackOrder() < getStackOrder()) // новый эффект слабее
  543.         {
  544.             if(newEffect.getTimeLeft() > getTimeLeft()) // новый эффект длинее
  545.             {
  546.                 newEffect.suspend();
  547.                 scheduleNext(newEffect); // пробуем пристроить новый эффект в очередь
  548.             }
  549.  
  550.             return false; // более слабый эффект всегда игнорируется, даже если не попал в очередь
  551.         }
  552.         else // если старый не дольше, то просто остановить его
  553.         if(newEffect.getTimeLeft() >= getTimeLeft())
  554.         {
  555.             // наследуем зашедуленый старому, если есть смысл
  556.             if(getNext() != null && getNext().getTimeLeft() > newEffect.getTimeLeft())
  557.             {
  558.                 newEffect.scheduleNext(getNext());
  559.                 // отсоединяем зашедуленные от текущего
  560.                 removeNext();
  561.             }
  562.             exit();
  563.         }
  564.         else
  565.         // если новый короче то зашедулить старый
  566.         {
  567.             suspend();
  568.             newEffect.scheduleNext(this);
  569.         }
  570.  
  571.         return true;
  572.     }
  573.  
  574.     public Func[] getStatFuncs()
  575.     {
  576.         return getTemplate().getStatFuncs(this);
  577.     }
  578.  
  579.     public void addIcon(AbnormalStatusUpdate mi)
  580.     {
  581.         if(!isActive() || isHidden())
  582.             return;
  583.         int duration = _skill.isToggle() ? AbnormalStatusUpdate.INFINITIVE_EFFECT : getTimeLeft();
  584.         mi.addEffect(_displayId, _displayLevel, duration);
  585.     }
  586.  
  587.     public void addPartySpelledIcon(PartySpelled ps)
  588.     {
  589.         if(!isActive() || isHidden())
  590.             return;
  591.         int duration = _skill.isToggle() ? AbnormalStatusUpdate.INFINITIVE_EFFECT : getTimeLeft();
  592.         ps.addPartySpelledEffect(_displayId, _displayLevel, duration);
  593.     }
  594.  
  595.     public void addOlympiadSpelledIcon(Player player, ExOlympiadSpelledInfo os)
  596.     {
  597.         if(!isActive() || isHidden())
  598.             return;
  599.         int duration = _skill.isToggle() ? AbnormalStatusUpdate.INFINITIVE_EFFECT : getTimeLeft();
  600.         os.addSpellRecivedPlayer(player);
  601.         os.addEffect(_displayId, _displayLevel, duration);
  602.     }
  603.  
  604.     protected int getLevel()
  605.     {
  606.         return _skill.getLevel();
  607.     }
  608.  
  609.     public EffectType getEffectType()
  610.     {
  611.         return getTemplate()._effectType;
  612.     }
  613.  
  614.     public boolean isHidden()
  615.     {
  616.         return _displayId < 0;
  617.     }
  618.  
  619.     @Override
  620.     public int compareTo(Effect obj)
  621.     {
  622.         if(obj.equals(this))
  623.             return 0;
  624.         return 1;
  625.     }
  626.  
  627.     public boolean isSaveable()
  628.     {
  629.         return _template.isSaveable(getSkill().isSaveable()) && getTimeLeft() >= Config.ALT_SAVE_EFFECTS_REMAINING_TIME;
  630.     }
  631.  
  632.     public int getDisplayId()
  633.     {
  634.         return _displayId;
  635.     }
  636.  
  637.     public int getDisplayLevel()
  638.     {
  639.         return _displayLevel;
  640.     }
  641.  
  642.     public boolean isCancelable()
  643.     {
  644.         return _template.isCancelable(getSkill().isCancelable());
  645.     }
  646.  
  647.     @Override
  648.     public String toString()
  649.     {
  650.         return "Skill: " + _skill + ", state: " + getState() + ", inUse: " + _inUse + ", active : " + _active;
  651.     }
  652.  
  653.     @Override
  654.     public boolean isFuncEnabled()
  655.     {
  656.         return isInUse();
  657.     }
  658.  
  659.     @Override
  660.     public boolean overrideLimits()
  661.     {
  662.         return false;
  663.     }
  664.  
  665.     public boolean isOffensive()
  666.     {
  667.         return _template.isOffensive(getSkill().isOffensive());
  668.     }
  669. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement