Package com.l2jfrozen.gameserver.model

Source Code of com.l2jfrozen.gameserver.model.L2Skill

/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* http://www.gnu.org/copyleft/gpl.html
*/
package com.l2jfrozen.gameserver.model;

import java.lang.reflect.Constructor;
import java.util.Collection;
import java.util.List;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;

import javolution.util.FastList;

import com.l2jfrozen.Config;
import com.l2jfrozen.gameserver.datatables.HeroSkillTable;
import com.l2jfrozen.gameserver.datatables.SkillTable;
import com.l2jfrozen.gameserver.datatables.sql.SkillTreeTable;
import com.l2jfrozen.gameserver.geo.GeoData;
import com.l2jfrozen.gameserver.managers.SiegeManager;
import com.l2jfrozen.gameserver.model.actor.instance.L2ArtefactInstance;
import com.l2jfrozen.gameserver.model.actor.instance.L2ChestInstance;
import com.l2jfrozen.gameserver.model.actor.instance.L2ControlTowerInstance;
import com.l2jfrozen.gameserver.model.actor.instance.L2DoorInstance;
import com.l2jfrozen.gameserver.model.actor.instance.L2MonsterInstance;
import com.l2jfrozen.gameserver.model.actor.instance.L2NpcInstance;
import com.l2jfrozen.gameserver.model.actor.instance.L2PcInstance;
import com.l2jfrozen.gameserver.model.actor.instance.L2PetInstance;
import com.l2jfrozen.gameserver.model.actor.instance.L2PlayableInstance;
import com.l2jfrozen.gameserver.model.actor.instance.L2SummonInstance;
import com.l2jfrozen.gameserver.model.base.ClassId;
import com.l2jfrozen.gameserver.model.entity.event.CTF;
import com.l2jfrozen.gameserver.model.entity.event.DM;
import com.l2jfrozen.gameserver.model.entity.event.TvT;
import com.l2jfrozen.gameserver.model.entity.siege.Siege;
import com.l2jfrozen.gameserver.network.SystemMessageId;
import com.l2jfrozen.gameserver.network.serverpackets.EtcStatusUpdate;
import com.l2jfrozen.gameserver.network.serverpackets.SystemMessage;
import com.l2jfrozen.gameserver.skills.BaseStats;
import com.l2jfrozen.gameserver.skills.Env;
import com.l2jfrozen.gameserver.skills.Formulas;
import com.l2jfrozen.gameserver.skills.Stats;
import com.l2jfrozen.gameserver.skills.conditions.Condition;
import com.l2jfrozen.gameserver.skills.effects.EffectCharge;
import com.l2jfrozen.gameserver.skills.effects.EffectTemplate;
import com.l2jfrozen.gameserver.skills.funcs.Func;
import com.l2jfrozen.gameserver.skills.funcs.FuncTemplate;
import com.l2jfrozen.gameserver.skills.l2skills.L2SkillCharge;
import com.l2jfrozen.gameserver.skills.l2skills.L2SkillChargeDmg;
import com.l2jfrozen.gameserver.skills.l2skills.L2SkillChargeEffect;
import com.l2jfrozen.gameserver.skills.l2skills.L2SkillCreateItem;
import com.l2jfrozen.gameserver.skills.l2skills.L2SkillDefault;
import com.l2jfrozen.gameserver.skills.l2skills.L2SkillDrain;
import com.l2jfrozen.gameserver.skills.l2skills.L2SkillSeed;
import com.l2jfrozen.gameserver.skills.l2skills.L2SkillSignet;
import com.l2jfrozen.gameserver.skills.l2skills.L2SkillSignetCasttime;
import com.l2jfrozen.gameserver.skills.l2skills.L2SkillSummon;
import com.l2jfrozen.gameserver.templates.StatsSet;
import com.l2jfrozen.gameserver.util.Util;

/**
* This class...
*
* @authors ProGramMoS, eX1steam, l2jfrozen dev
* @version $Revision: 1.3.3 $ $Date: 2009/04/29 00:08 $
*/
public abstract class L2Skill
{
  protected static final Logger _log = Logger.getLogger(L2Skill.class.getName());

  public static final int SKILL_CUBIC_MASTERY = 143;
  public static final int SKILL_LUCKY = 194;
  public static final int SKILL_CREATE_COMMON = 1320;
  public static final int SKILL_CREATE_DWARVEN = 172;
  public static final int SKILL_CRYSTALLIZE = 248;
  public static final int SKILL_DIVINE_INSPIRATION = 1405;

  public static final int SKILL_FAKE_INT = 9001;
  public static final int SKILL_FAKE_WIT = 9002;
  public static final int SKILL_FAKE_MEN = 9003;
  public static final int SKILL_FAKE_CON = 9004;
  public static final int SKILL_FAKE_DEX = 9005;
  public static final int SKILL_FAKE_STR = 9006;

  private final int _targetConsumeId;
  private final int _targetConsume;
 
  public static enum SkillOpType
  {
    OP_PASSIVE,
    OP_ACTIVE,
    OP_TOGGLE,
    OP_CHANCE
  }

  /** Target types of skills : SELF, PARTY, CLAN, PET... */
  public static enum SkillTargetType
  {
    TARGET_NONE,
    TARGET_SELF,
    TARGET_ONE,
    TARGET_PARTY,
    TARGET_ALLY,
    TARGET_CLAN,
    TARGET_PET,
    TARGET_AREA,
    TARGET_AURA,
    TARGET_CORPSE,
    TARGET_UNDEAD,
    TARGET_AREA_UNDEAD,
    TARGET_MULTIFACE,
    TARGET_CORPSE_ALLY,
    TARGET_CORPSE_CLAN,
    TARGET_CORPSE_PLAYER,
    TARGET_CORPSE_PET,
    TARGET_ITEM,
    TARGET_AREA_CORPSE_MOB,
    TARGET_CORPSE_MOB,
    TARGET_UNLOCKABLE,
    TARGET_HOLY,
    TARGET_PARTY_MEMBER,
    TARGET_PARTY_OTHER,
    TARGET_ENEMY_SUMMON,
    TARGET_OWNER_PET,
    TARGET_GROUND,
    TARGET_SIEGE,
    TARGET_TYRANNOSAURUS,
    TARGET_AREA_AIM_CORPSE,
    TARGET_CLAN_MEMBER
  }

  public static enum SkillType
  {
    // Damage
    PDAM,
    MDAM,
    CPDAM,
    MANADAM,
    DOT,
    MDOT,
    DRAIN_SOUL,
    DRAIN(L2SkillDrain.class),
    DEATHLINK,
    FATALCOUNTER,
    BLOW,

    // Disablers
    BLEED,
    POISON,
    STUN,
    ROOT,
    CONFUSION,
    FEAR,
    SLEEP,
    CONFUSE_MOB_ONLY,
    MUTE,
    PARALYZE,
    WEAKNESS,

    // hp, mp, cp
    HEAL,
    HOT,
    BALANCE_LIFE,
    HEAL_PERCENT,
    HEAL_STATIC,
    CPHEAL_PERCENT,
    COMBATPOINTHEAL,
    COMBATPOINTPERCENTHEAL,
    CPHOT,
    MANAHEAL,
    MANA_BY_LEVEL,
    MANAHEAL_PERCENT,
    MANARECHARGE,
    MPHOT,

    // Aggro
    AGGDAMAGE,
    AGGREDUCE,
    AGGREMOVE,
    AGGREDUCE_CHAR,
    AGGDEBUFF,

    // Fishing
    FISHING,
    PUMPING,
    REELING,

    // MISC
    UNLOCK,
    ENCHANT_ARMOR,
    ENCHANT_WEAPON,
    SOULSHOT,
    SPIRITSHOT,
    SIEGEFLAG,
    TAKECASTLE,
    DELUXE_KEY_UNLOCK,
    SOW,
    HARVEST,
    GET_PLAYER,

    // Creation
    COMMON_CRAFT,
    DWARVEN_CRAFT,
    CREATE_ITEM(L2SkillCreateItem.class),
    SUMMON_TREASURE_KEY,

    // Summons
    SUMMON(L2SkillSummon.class),
    FEED_PET,
    DEATHLINK_PET,
    STRSIEGEASSAULT,
    ERASE,
    BETRAY,

    // Cancel
    CANCEL,
    MAGE_BANE,
    WARRIOR_BANE,
    NEGATE,

    BUFF,
    DEBUFF,
    PASSIVE,
    CONT,
    SIGNET(L2SkillSignet.class),
    SIGNET_CASTTIME(L2SkillSignetCasttime.class),

    RESURRECT,
    CHARGE(L2SkillCharge.class),
    CHARGE_EFFECT(L2SkillChargeEffect.class),
    CHARGEDAM(L2SkillChargeDmg.class),
    MHOT,
    DETECT_WEAKNESS,
    LUCK,
    RECALL,
    SUMMON_FRIEND,
    REFLECT,
    SPOIL,
    SWEEP,
    FAKE_DEATH,
    UNBLEED,
    UNPOISON,
    UNDEAD_DEFENSE,
    SEED(L2SkillSeed.class),
    BEAST_FEED,
    FORCE_BUFF,
    CLAN_GATE,
    GIVE_SP,
    COREDONE,
    ZAKENPLAYER,
    ZAKENSELF,
    TELEPORT,

    // unimplemented
    NOTDONE;

    private final Class<? extends L2Skill> _class;

    public L2Skill makeSkill(StatsSet set)
    {
      try
      {
        Constructor<? extends L2Skill> c = _class.getConstructor(StatsSet.class);

        return c.newInstance(set);
      }
      catch(Exception e)
      {
        throw new RuntimeException(e);
      }
    }

    private SkillType()
    {
      _class = L2SkillDefault.class;
    }

    private SkillType(Class<? extends L2Skill> classType)
    {
      _class = classType;
    }
  }

  protected ChanceCondition _chanceCondition = null;
  //elements
  public final static int ELEMENT_WIND = 1;
  public final static int ELEMENT_FIRE = 2;
  public final static int ELEMENT_WATER = 3;
  public final static int ELEMENT_EARTH = 4;
  public final static int ELEMENT_HOLY = 5;
  public final static int ELEMENT_DARK = 6;

  //stat effected
  public final static int STAT_PATK = 301; // pAtk
  public final static int STAT_PDEF = 302; // pDef
  public final static int STAT_MATK = 303; // mAtk
  public final static int STAT_MDEF = 304; // mDef
  public final static int STAT_MAXHP = 305; // maxHp
  public final static int STAT_MAXMP = 306; // maxMp
  public final static int STAT_CURHP = 307;
  public final static int STAT_CURMP = 308;
  public final static int STAT_HPREGEN = 309; // regHp
  public final static int STAT_MPREGEN = 310; // regMp
  public final static int STAT_CASTINGSPEED = 311; // sCast
  public final static int STAT_ATKSPD = 312; // sAtk
  public final static int STAT_CRITDAM = 313; // critDmg
  public final static int STAT_CRITRATE = 314; // critRate
  public final static int STAT_FIRERES = 315; // fireRes
  public final static int STAT_WINDRES = 316; // windRes
  public final static int STAT_WATERRES = 317; // waterRes
  public final static int STAT_EARTHRES = 318; // earthRes
  public final static int STAT_HOLYRES = 336; // holyRes
  public final static int STAT_DARKRES = 337; // darkRes
  public final static int STAT_ROOTRES = 319; // rootRes
  public final static int STAT_SLEEPRES = 320; // sleepRes
  public final static int STAT_CONFUSIONRES = 321; // confusRes
  public final static int STAT_BREATH = 322; // breath
  public final static int STAT_AGGRESSION = 323; // aggr
  public final static int STAT_BLEED = 324; // bleed
  public final static int STAT_POISON = 325; // poison
  public final static int STAT_STUN = 326; // stun
  public final static int STAT_ROOT = 327; // root
  public final static int STAT_MOVEMENT = 328; // move
  public final static int STAT_EVASION = 329; // evas
  public final static int STAT_ACCURACY = 330; // accu
  public final static int STAT_COMBAT_STRENGTH = 331;
  public final static int STAT_COMBAT_WEAKNESS = 332;
  public final static int STAT_ATTACK_RANGE = 333; // rAtk
  public final static int STAT_NOAGG = 334; // noagg
  public final static int STAT_SHIELDDEF = 335; // sDef
  public final static int STAT_MP_CONSUME_RATE = 336; // Rate of mp consume per skill use
  public final static int STAT_HP_CONSUME_RATE = 337; // Rate of hp consume per skill use
  public final static int STAT_MCRITRATE = 338; // Magic Crit Rate

  //COMBAT DAMAGE MODIFIER SKILLS...DETECT WEAKNESS AND WEAKNESS/STRENGTH
  public final static int COMBAT_MOD_ANIMAL = 200;
  public final static int COMBAT_MOD_BEAST = 201;
  public final static int COMBAT_MOD_BUG = 202;
  public final static int COMBAT_MOD_DRAGON = 203;
  public final static int COMBAT_MOD_MONSTER = 204;
  public final static int COMBAT_MOD_PLANT = 205;
  public final static int COMBAT_MOD_HOLY = 206;
  public final static int COMBAT_MOD_UNHOLY = 207;
  public final static int COMBAT_MOD_BOW = 208;
  public final static int COMBAT_MOD_BLUNT = 209;
  public final static int COMBAT_MOD_DAGGER = 210;
  public final static int COMBAT_MOD_FIST = 211;
  public final static int COMBAT_MOD_DUAL = 212;
  public final static int COMBAT_MOD_SWORD = 213;
  public final static int COMBAT_MOD_POISON = 214;
  public final static int COMBAT_MOD_BLEED = 215;
  public final static int COMBAT_MOD_FIRE = 216;
  public final static int COMBAT_MOD_WATER = 217;
  public final static int COMBAT_MOD_EARTH = 218;
  public final static int COMBAT_MOD_WIND = 219;
  public final static int COMBAT_MOD_ROOT = 220;
  public final static int COMBAT_MOD_STUN = 221;
  public final static int COMBAT_MOD_CONFUSION = 222;
  public final static int COMBAT_MOD_DARK = 223;

  //conditional values
  public final static int COND_RUNNING = 0x0001;
  public final static int COND_WALKING = 0x0002;
  public final static int COND_SIT = 0x0004;
  public final static int COND_BEHIND = 0x0008;
  public final static int COND_CRIT = 0x0010;
  public final static int COND_LOWHP = 0x0020;
  public final static int COND_ROBES = 0x0040;
  public final static int COND_CHARGES = 0x0080;
  public final static int COND_SHIELD = 0x0100;
  public final static int COND_GRADEA = 0x010000;
  public final static int COND_GRADEB = 0x020000;
  public final static int COND_GRADEC = 0x040000;
  public final static int COND_GRADED = 0x080000;
  public final static int COND_GRADES = 0x100000;

  private static final Func[] _emptyFunctionSet = new Func[0];
  private static final L2Effect[] _emptyEffectSet = new L2Effect[0];

  // these two build the primary key
  private final int _id;
  private final int _level;

  /** Identifier for a skill that client can't display */
  private int _displayId;

  // not needed, just for easier debug
  private final String _name;
  private final SkillOpType _operateType;
  private final boolean _magic;
  private final boolean _staticReuse;
  private final boolean _staticHitTime;
  private final int _mpConsume;
  private final int _mpInitialConsume;
  private final int _hpConsume;
  private final int _itemConsume;
  private final int _itemConsumeId;
  // item consume count over time
  protected int _itemConsumeOT;
  // item consume id over time
  protected int _itemConsumeIdOT;
  // how many times to consume an item
  protected int _itemConsumeSteps;
  // for summon spells:
  // a) What is the total lifetime of summons (in millisecs)
  private int _summonTotalLifeTime;
  // b) how much lifetime is lost per second of idleness (non-fighting)
  protected int _summonTimeLostIdle;
  // c) how much time is lost per second of activity (fighting)
  protected int _summonTimeLostActive;

  // item consume time in milliseconds
  protected int _itemConsumeTime;
  private final int _castRange;
  private final int _effectRange;

  // all times in milliseconds
  private final int _hitTime;
  //private final int _skillInterruptTime;
  private final int _coolTime;
  private final int _reuseDelay;
  private final int _buffDuration;

  /** Target type of the skill : SELF, PARTY, CLAN, PET... */
  private final SkillTargetType _targetType;

  private final double _power;
  private final int _effectPoints;
  private final int _magicLevel;
  private final String[] _negateSkillTypes;
  private final String[] _negateEffectTypes;
  private final float _negatePower;
  private final int _negateId;
  private final int _levelDepend;

  // Effecting area of the skill, in radius.
  // The radius center varies according to the _targetType:
  // "caster" if targetType = AURA/PARTY/CLAN or "target" if targetType = AREA
  private final int _skillRadius;

  private final SkillType _skillType;
  private final SkillType _effectType;
  private final int _effectPower;
  private final int _effectId;
  private final int _effectLvl;

  private final boolean _ispotion;
  private final int _element;
  private final BaseStats _saveVs;
 
  private final boolean _isSuicideAttack;

  private final Stats _stat;

  private final int _condition;
  private final int _conditionValue;
  private final boolean _overhit;
  private final int _weaponsAllowed;
  private final int _armorsAllowed;

  private final int _addCrossLearn; // -1 disable, otherwice SP price for others classes, default 1000
  private final float _mulCrossLearn; // multiplay for others classes, default 2
  private final float _mulCrossLearnRace; // multiplay for others races, default 2
  private final float _mulCrossLearnProf; // multiplay for fighter/mage missmatch, default 3
  private final List<ClassId> _canLearn; // which classes can learn
  private final List<Integer> _teachers; // which NPC teaches
  private final int _minPledgeClass;

  private final boolean _isOffensive;
  private final int _numCharges;
  private final int _triggeredId;
  private final int _triggeredLevel;

  private final boolean _bestowed;

  private final boolean _isHeroSkill; // If true the skill is a Hero Skill

  private final int _baseCritRate; // percent of success for skill critical hit (especially for PDAM & BLOW - they're not affected by rCrit values or buffs). Default loads -1 for all other skills but 0 to PDAM & BLOW
  private final int _lethalEffect1; // percent of success for lethal 1st effect (hit cp to 1 or if mob hp to 50%) (only for PDAM skills)
  private final int _lethalEffect2; // percent of success for lethal 2nd effect (hit cp,hp to 1 or if mob hp to 1) (only for PDAM skills)
  private final boolean _directHpDmg; // If true then dmg is being make directly
  private final boolean _isDance; // If true then casting more dances will cost more MP
  private final int _nextDanceCost;
  private final float _sSBoost; //If true skill will have SoulShot boost (power*2)
  private final int _aggroPoints;

  private final float _pvpMulti;

  protected Condition _preCondition;
  protected Condition _itemPreCondition;
  protected FuncTemplate[] _funcTemplates;
  protected EffectTemplate[] _effectTemplates;
  protected EffectTemplate[] _effectTemplatesSelf;

  private final boolean _nextActionIsAttack;
 
  private final int _minChance;
  private final int _maxChance;
 
  private final boolean _singleEffect;
 
  private final boolean _isDebuff;
 
  private final boolean _advancedFlag;
  private final int _advancedMultiplier; 
 
  protected L2Skill(StatsSet set)
  {
    _id = set.getInteger("skill_id",0);
    _level = set.getInteger("level",1);
   
    _advancedFlag = set.getBool("advancedFlag", false);
    _advancedMultiplier = set.getInteger("advancedMultiplier",1);

    _displayId = set.getInteger("displayId", _id);
    _name = set.getString("name");
    _operateType = set.getEnum("operateType", SkillOpType.class);
    _magic = set.getBool("isMagic", false);
    _staticReuse = set.getBool("staticReuse", false);
    _staticHitTime = set.getBool("staticHitTime", false);
    _ispotion = set.getBool("isPotion", false);
    _mpConsume = set.getInteger("mpConsume", 0);
    _mpInitialConsume = set.getInteger("mpInitialConsume", 0);
    _hpConsume = set.getInteger("hpConsume", 0);
    _itemConsume = set.getInteger("itemConsumeCount", 0);
    _itemConsumeId = set.getInteger("itemConsumeId", 0);
    _itemConsumeOT = set.getInteger("itemConsumeCountOT", 0);
    _itemConsumeIdOT = set.getInteger("itemConsumeIdOT", 0);
    _itemConsumeTime = set.getInteger("itemConsumeTime", 0);
    _itemConsumeSteps = set.getInteger("itemConsumeSteps", 0);
    _summonTotalLifeTime = set.getInteger("summonTotalLifeTime", 1200000); // 20 minutes default
    _summonTimeLostIdle = set.getInteger("summonTimeLostIdle", 0);
    _summonTimeLostActive = set.getInteger("summonTimeLostActive", 0);

    _castRange = set.getInteger("castRange", 0);
    _effectRange = set.getInteger("effectRange", -1);

    _hitTime = set.getInteger("hitTime", 0);
    _coolTime = set.getInteger("coolTime", 0);
    //_skillInterruptTime = set.getInteger("hitTime", _hitTime / 2);
    _reuseDelay = set.getInteger("reuseDelay", 0);
    _buffDuration = set.getInteger("buffDuration", 0);

    _skillRadius = set.getInteger("skillRadius", 80);

    _targetType = set.getEnum("target", SkillTargetType.class);
    _power = set.getFloat("power", 0.f);
    _effectPoints = set.getInteger("effectPoints", 0);
    _negateSkillTypes = set.getString("negateSkillTypes", "").split(" ");
    _negateEffectTypes = set.getString("negateEffectTypes", "").split(" ");
    _negatePower = set.getFloat("negatePower", 0.f);
    _negateId = set.getInteger("negateId", 0);
    _magicLevel = set.getInteger("magicLvl", SkillTreeTable.getInstance().getMinSkillLevel(_id, _level));
    _levelDepend = set.getInteger("lvlDepend", 0);
    _stat = set.getEnum("stat", Stats.class, null);

    _skillType = set.getEnum("skillType", SkillType.class);
    _effectType = set.getEnum("effectType", SkillType.class, null);
    _effectPower = set.getInteger("effectPower", 0);
    _effectId = set.getInteger("effectId", 0);
    _effectLvl = set.getInteger("effectLevel", 0);

    _element = set.getInteger("element", 0);
    _saveVs = set.getEnum("saveVs", BaseStats.class, null);
   
    _condition = set.getInteger("condition", 0);
    _conditionValue = set.getInteger("conditionValue", 0);
    _overhit = set.getBool("overHit", false);
    _isSuicideAttack = set.getBool("isSuicideAttack", false);
    _weaponsAllowed = set.getInteger("weaponsAllowed", 0);
    _armorsAllowed = set.getInteger("armorsAllowed", 0);

    _addCrossLearn = set.getInteger("addCrossLearn", 1000);
    _mulCrossLearn = set.getFloat("mulCrossLearn", 2.f);
    _mulCrossLearnRace = set.getFloat("mulCrossLearnRace", 2.f);
    _mulCrossLearnProf = set.getFloat("mulCrossLearnProf", 3.f);
    _minPledgeClass = set.getInteger("minPledgeClass", 0);
    _isOffensive = set.getBool("offensive", isSkillTypeOffensive());
    _numCharges = set.getInteger("num_charges", 0);
    _triggeredId = set.getInteger("triggeredId", 0);
    _triggeredLevel = set.getInteger("triggeredLevel", 0);

    _bestowed = set.getBool("bestowed", false);

    _targetConsume = set.getInteger("targetConsumeCount", 0);
    _targetConsumeId = set.getInteger("targetConsumeId", 0);
   
    if(_operateType == SkillOpType.OP_CHANCE)
    {
      _chanceCondition = ChanceCondition.parse(set);
    }

    _isHeroSkill = HeroSkillTable.isHeroSkill(_id);

    _baseCritRate = set.getInteger("baseCritRate", _skillType == SkillType.PDAM || _skillType == SkillType.BLOW ? 0 : -1);
    _lethalEffect1 = set.getInteger("lethal1", 0);
    _lethalEffect2 = set.getInteger("lethal2", 0);

    _directHpDmg = set.getBool("dmgDirectlyToHp", false);
    _isDance = set.getBool("isDance", false);
    _nextDanceCost = set.getInteger("nextDanceCost", 0);
    _sSBoost = set.getFloat("SSBoost", 0.f);
    _aggroPoints = set.getInteger("aggroPoints", 0);

    _pvpMulti = set.getFloat("pvpMulti", 1.f);

    _nextActionIsAttack = set.getBool("nextActionAttack", false);
   
    _minChance = set.getInteger("minChance", 1);
    _maxChance = set.getInteger("maxChance", 99);
   
    String canLearn = set.getString("canLearn", null);
    if(canLearn == null)
    {
      _canLearn = null;
    }
    else
    {
      _canLearn = new FastList<ClassId>();
      StringTokenizer st = new StringTokenizer(canLearn, " \r\n\t,;");

      while(st.hasMoreTokens())
      {
        String cls = st.nextToken();
        try
        {
          _canLearn.add(ClassId.valueOf(cls));
        }
        catch(Throwable t)
        {
          _log.log(Level.SEVERE, "Bad class " + cls + " to learn skill", t);
        }
        cls = null;
      }

      st = null;
    }

    canLearn = null;

    String teachers = set.getString("teachers", null);
    if(teachers == null)
    {
      _teachers = null;
    }
    else
    {
      _teachers = new FastList<Integer>();
      StringTokenizer st = new StringTokenizer(teachers, " \r\n\t,;");
      while(st.hasMoreTokens())
      {
        String npcid = st.nextToken();
        try
        {
          _teachers.add(Integer.parseInt(npcid));
        }
        catch(Throwable t)
        {
          _log.log(Level.SEVERE, "Bad teacher id " + npcid + " to teach skill", t);
        }

        npcid = null;
      }

      st = null;
    }

    teachers = null;
   
    _singleEffect = set.getBool("singleEffect", false);
   
    _isDebuff = set.getBool("isDebuff", false);
   
  }

  public abstract void useSkill(L2Character caster, L2Object[] targets);

 
  /**
   * @return the _singleEffect
   */
  public boolean is_singleEffect()
  {
    return _singleEffect;
  }
 
  /**
   * @return the _isDebuff
   */
  public boolean is_Debuff()
  {
    boolean type_debuff = false;
   
    switch(_skillType){
      case AGGDEBUFF:
      case DEBUFF:
      case STUN:
      case BLEED:
      case CONFUSION:
      case FEAR:
      case PARALYZE:
      case SLEEP:
      case ROOT:
      case POISON:
      case MUTE:
      case WEAKNESS:
        type_debuff = true;
       
    }
   
    return _isDebuff || type_debuff;
  }

  /**
   * @return true if character should attack target after skill
   */
  public final boolean nextActionIsAttack()
  {
    return _nextActionIsAttack;
  }
 
  public final boolean isPotion()
  {
    return _ispotion;
  }

  public final int getArmorsAllowed()
  {
    return _armorsAllowed;
  }

  public final int getConditionValue()
  {
    return _conditionValue;
  }

  public final SkillType getSkillType()
  {
    return _skillType;
  }

  public final boolean hasEffectWhileCasting()
  {
    return getSkillType() == SkillType.SIGNET_CASTTIME;
  }

  public final BaseStats getSavevs()
  {
    return _saveVs;
  }

  public final int getElement()
  {
    return _element;
  }

  /**
   * @return the target type of the skill : SELF, PARTY, CLAN, PET...
   */
  public final SkillTargetType getTargetType()
  {
    return _targetType;
  }

  public final int getCondition()
  {
    return _condition;
  }

  public final boolean isOverhit()
  {
    return _overhit;
  }

  public final boolean isSuicideAttack()
  {
    return _isSuicideAttack;
  }

  /**
   * @param activeChar
   * @return the power of the skill.
   */
  public final double getPower(L2Character activeChar)
  {
    /*if(_skillType == SkillType.DEATHLINK && activeChar != null)
      return _power * Math.pow(1.7165 - activeChar.getCurrentHp() / activeChar.getMaxHp(), 2) * 0.577;
    else */
    if(_skillType == SkillType.FATALCOUNTER && activeChar != null)
      return _power * 3.5 * (1 - activeChar.getCurrentHp() / activeChar.getMaxHp());
    return _power;
  }

  public final double getPower()
  {
    return _power;
  }

  public final int getEffectPoints()
  {
    return _effectPoints;
  }

  public final String[] getNegateSkillTypes()
  {
    return _negateSkillTypes;
  }
 
  public final String[] getNegateEffectTypes()
  {
    return _negateEffectTypes;
  }

  public final float getNegatePower()
  {
    return _negatePower;
  }

  public final int getNegateId()
  {
    return _negateId;
  }

  public final int getMagicLevel()
  {
    return _magicLevel;
  }

  /**
   * @return Returns true to set static reuse.
   */
  public final boolean isStaticReuse()
  {
    return _staticReuse;
  }

  /**
   * @return Returns true to set static hittime.
   */
  public final boolean isStaticHitTime()
  {
    return _staticHitTime;
  }

  public final int getLevelDepend()
  {
    return _levelDepend;
  }

  /**
   * @return the additional effect power or base probability.
   */
  public final int getEffectPower()
  {
    return _effectPower;
  }

  /**
   * @return the additional effect Id.
   */
  public final int getEffectId()
  {
    return _effectId;
  }

  /**
   * @return the additional effect level.
   */
  public final int getEffectLvl()
  {
    return _effectLvl;
  }

  /**
   * @return the additional effect skill type (ex : STUN, PARALYZE,...).
   */
  public final SkillType getEffectType()
  {
    return _effectType;
  }

  /**
   * @return Returns the buffDuration.
   */
  public final int getBuffDuration()
  {
    return _buffDuration;
  }

  /**
   * @return Returns the castRange.
   */
  public final int getCastRange()
  {
    return _castRange;
  }

  /**
   * @return Returns the effectRange.
   */
  public final int getEffectRange()
  {
    return _effectRange;
  }

  /**
   * @return Returns the hpConsume.
   */
  public final int getHpConsume()
  {
    return _hpConsume;
  }

  /**
   * @return Returns the id.
   */
  public final int getId()
  {
    return _id;
  }

  public int getDisplayId()
  {
    return _displayId;
  }

  public void setDisplayId(int id)
  {
    _displayId = id;
  }

  public int getTriggeredId()
  {
    return _triggeredId;
  }

  public int getTriggeredLevel()
  {
    return _triggeredLevel;
  }

  /**
   * @return the skill type (ex : BLEED, SLEEP, WATER...).
   */
  public final Stats getStat()
  {
    return _stat;
  }

  /**
   * @return Returns the itemConsume.
   */
  public final int getItemConsume()
  {
    return _itemConsume;
  }

  /**
   * @return Returns the itemConsumeId.
   */
  public final int getItemConsumeId()
  {
    return _itemConsumeId;
  }

  /**
   * @return Returns the itemConsume count over time.
   */
  public final int getItemConsumeOT()
  {
    return _itemConsumeOT;
  }

  /**
   * @return Returns the itemConsumeId over time.
   */
  public final int getItemConsumeIdOT()
  {
    return _itemConsumeIdOT;
  }

  /**
   * @return Returns the itemConsume count over time.
   */
  public final int getItemConsumeSteps()
  {
    return _itemConsumeSteps;
  }

  /**
   * @return Returns the itemConsume count over time.
   */
  public final int getTotalLifeTime()
  {
    return _summonTotalLifeTime;
  }

  /**
   * @return Returns the itemConsume count over time.
   */
  public final int getTimeLostIdle()
  {
    return _summonTimeLostIdle;
  }

  /**
   * @return Returns the itemConsumeId over time.
   */
  public final int getTimeLostActive()
  {
    return _summonTimeLostActive;
  }

  /**
   * @return Returns the itemConsume time in milliseconds.
   */
  public final int getItemConsumeTime()
  {
    return _itemConsumeTime;
  }

  /**
   * @return Returns the level.
   */
  public final int getLevel()
  {
    return _level;
  }

  /**
   * @return Returns the magic.
   */
  public final boolean isMagic()
  {
    return _magic;
  }

  /**
   * @return Returns the mpConsume.
   */
  public final int getMpConsume()
  {
    return _mpConsume;
  }

  /**
   * @return Returns the mpInitialConsume.
   */
  public final int getMpInitialConsume()
  {
    return _mpInitialConsume;
  }

  /**
   * @return Returns the name.
   */
  public final String getName()
  {
    return _name;
  }

  /**
   * @return Returns the reuseDelay.
   */
  public final int getReuseDelay()
  {
    return _reuseDelay;
  }

  @Deprecated
  public final int getSkillTime()
  {
    return _hitTime;
  }

  public final int getHitTime()
  {
    return _hitTime;
  }

  /**
   * @return Returns the coolTime.
   */
  public final int getCoolTime()
  {
    return _coolTime;
  }

  public final int getSkillRadius()
  {
    return _skillRadius;
  }

  public final boolean isActive()
  {
    return _operateType == SkillOpType.OP_ACTIVE;
  }

  public final boolean isPassive()
  {
    return _operateType == SkillOpType.OP_PASSIVE;
  }

  public final boolean isToggle()
  {
    return _operateType == SkillOpType.OP_TOGGLE;
  }

  public final boolean isChance()
  {
    return _operateType == SkillOpType.OP_CHANCE;
  }

  public ChanceCondition getChanceCondition()
  {
    return _chanceCondition;
  }

  public final boolean isDance()
  {
    return _isDance;
  }

  public final int getNextDanceMpCost()
  {
    return _nextDanceCost;
  }

  public final float getSSBoost()
  {
    return _sSBoost;
  }

  public final int getAggroPoints()
  {
    return _aggroPoints;
  }

  public final float getPvpMulti()
  {
    return _pvpMulti;
  }

  public final boolean useSoulShot()
  {
    return getSkillType() == SkillType.PDAM || getSkillType() == SkillType.STUN || getSkillType() == SkillType.CHARGEDAM || getSkillType() == SkillType.BLOW;
  }

  public final boolean useSpiritShot()
  {
    return isMagic();
  }

  public final boolean useFishShot()
  {
    return getSkillType() == SkillType.PUMPING || getSkillType() == SkillType.REELING;
  }

  public final int getWeaponsAllowed()
  {
    return _weaponsAllowed;
  }

  public final int getCrossLearnAdd()
  {
    return _addCrossLearn;
  }

  public final float getCrossLearnMul()
  {
    return _mulCrossLearn;
  }

  public final float getCrossLearnRace()
  {
    return _mulCrossLearnRace;
  }

  public final float getCrossLearnProf()
  {
    return _mulCrossLearnProf;
  }

  public final boolean getCanLearn(ClassId cls)
  {
    return _canLearn == null || _canLearn.contains(cls);
  }

  public final boolean canTeachBy(int npcId)
  {
    return _teachers == null || _teachers.contains(npcId);
  }

  public int getMinPledgeClass()
  {
    return _minPledgeClass;
  }

  public final boolean isPvpSkill()
  {
    switch(_skillType)
    {
      case DOT:
      case AGGREDUCE:
      case AGGDAMAGE:
      case AGGREDUCE_CHAR:
      case CONFUSE_MOB_ONLY:
      case BLEED:
      case CONFUSION:
      case POISON:
      case DEBUFF:
      case AGGDEBUFF:
      case STUN:
      case ROOT:
      case FEAR:
      case SLEEP:
      case MDOT:
      case MANADAM:
      case MUTE:
      case WEAKNESS:
      case PARALYZE:
      case CANCEL:
      case MAGE_BANE:
      case WARRIOR_BANE:
      case FATALCOUNTER:
      case BETRAY:
        return true;
      default:
        return false;
    }
  }

  public final boolean isOffensive()
  {
    return _isOffensive;
  }

  public final boolean isHeroSkill()
  {
    return _isHeroSkill;
  }

  public final int getNumCharges()
  {
    return _numCharges;
  }

  public final int getBaseCritRate()
  {
    return _baseCritRate;
  }

  public final int getLethalChance1()
  {
    return _lethalEffect1;
  }

  public final int getLethalChance2()
  {
    return _lethalEffect2;
  }

  public final boolean getDmgDirectlyToHP()
  {
    return _directHpDmg;
  }

  public boolean bestowed()
  {
    return _bestowed;
  }

  public boolean triggerAnotherSkill()
  {
    return _triggeredId > 1;
  }

  public final boolean isSkillTypeOffensive()
  {
    switch(_skillType)
    {
      case PDAM:
      case MDAM:
      case CPDAM:
      case DOT:
      case BLEED:
      case POISON:
      case AGGDAMAGE:
      case DEBUFF:
      case AGGDEBUFF:
      case STUN:
      case ROOT:
      case CONFUSION:
      case ERASE:
      case BLOW:
      case FEAR:
      case DRAIN:
      case SLEEP:
      case CHARGEDAM:
      case CONFUSE_MOB_ONLY:
      case DEATHLINK:
      case DETECT_WEAKNESS:
      case MANADAM:
      case MDOT:
      case MUTE:
      case SOULSHOT:
      case SPIRITSHOT:
      case SPOIL:
      case WEAKNESS:
      case MANA_BY_LEVEL:
      case SWEEP:
      case PARALYZE:
      case DRAIN_SOUL:
      case AGGREDUCE:
      case CANCEL:
      case MAGE_BANE:
      case WARRIOR_BANE:
      case AGGREMOVE:
      case AGGREDUCE_CHAR:
      case FATALCOUNTER:
      case BETRAY:
      case DELUXE_KEY_UNLOCK:
      case SOW:
      case HARVEST:
        return true;
      default:
        return false;
    }
  }

  //  int weapons[] = {L2Weapon.WEAPON_TYPE_ETC, L2Weapon.WEAPON_TYPE_BOW,
  //  L2Weapon.WEAPON_TYPE_POLE, L2Weapon.WEAPON_TYPE_DUALFIST,
  //  L2Weapon.WEAPON_TYPE_DUAL, L2Weapon.WEAPON_TYPE_BLUNT,
  //  L2Weapon.WEAPON_TYPE_SWORD, L2Weapon.WEAPON_TYPE_DAGGER};

  public final boolean getWeaponDependancy(L2Character activeChar)
  {
    if(getWeaponDependancy(activeChar, false))
      return true;
    SystemMessage message = new SystemMessage(SystemMessageId.S1_CANNOT_BE_USED);
    message.addSkillName(this.getId());
    activeChar.sendPacket(message);

    return false;
  }

  public final boolean getWeaponDependancy(L2Character activeChar, boolean chance)
  {
    int weaponsAllowed = getWeaponsAllowed();
    //check to see if skill has a weapon dependency.
    if(weaponsAllowed == 0)
      return true;

    int mask = 0;
    if(activeChar.getActiveWeaponItem() != null)
    {
      mask |= activeChar.getActiveWeaponItem().getItemType().mask();
    }
    if(activeChar.getSecondaryWeaponItem() != null)
    {
      mask |= activeChar.getSecondaryWeaponItem().getItemType().mask();
    }

    if((mask & weaponsAllowed) != 0)
      return true;

    return false;
  }

  public boolean checkCondition(L2Character activeChar, L2Object target, boolean itemOrWeapon)
  {
    Condition preCondition = _preCondition;

    if(itemOrWeapon)
    {
      preCondition = _itemPreCondition;
    }

    if(preCondition == null)
      return true;

    Env env = new Env();
    env.player = activeChar;
    if(target instanceof L2Character)
    {
      env.target = (L2Character) target;
    }

    env.skill = this;
    if(!preCondition.test(env))
    {
      String msg = preCondition.getMessage();
      if(msg != null)
      {
        SystemMessage sm = new SystemMessage(SystemMessageId.S1_S2);
        sm.addString(msg);
        activeChar.sendPacket(sm);
        sm = null;
      }

      msg = null;

      return false;
    }

    env = null;
    preCondition = null;

    return true;
  }

  public final L2Object[] getTargetList(L2Character activeChar, boolean onlyFirst)
  {
    // Init to null the target of the skill
    L2Character target = null;

    // Get the L2Objcet targeted by the user of the skill at this moment
    L2Object objTarget = activeChar.getTarget();
    // If the L2Object targeted is a L2Character, it becomes the L2Character target
    if(objTarget instanceof L2Character)
    {
      target = (L2Character) objTarget;
    }

    return getTargetList(activeChar, onlyFirst, target);
  }

  /**
   * Return all targets of the skill in a table in function a the skill type.<BR>
   * <BR>
   * <B><U> Values of skill type</U> :</B><BR>
   * <BR>
   * <li>ONE : The skill can only be used on the L2PcInstance targeted, or on the caster if it's a L2PcInstance and no
   * L2PcInstance targeted</li> <li>SELF</li> <li>HOLY, UNDEAD</li> <li>PET</li> <li>AURA, AURA_CLOSE</li> <li>AREA</li>
   * <li>MULTIFACE</li> <li>PARTY, CLAN</li> <li>CORPSE_PLAYER, CORPSE_MOB, CORPSE_CLAN</li> <li>UNLOCKABLE</li> <li>
   * ITEM</li><BR>
   * <BR>
   *
   * @param activeChar The L2Character who use the skill
   * @param onlyFirst
   * @param target
   * @return
   */
  public final L2Object[] getTargetList(L2Character activeChar, boolean onlyFirst, L2Character target)
  {
    if( activeChar instanceof L2PcInstance  ){ //to avoid attacks during oly start period
     
      if(isOffensive() && (((L2PcInstance)activeChar).isInOlympiadMode() && !((L2PcInstance)activeChar).isOlympiadStart())){
        activeChar.sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
        return null;
      }
     
    }

    List<L2Character> targetList = new FastList<L2Character>();

    if(isPotion()){
     
      return new L2Character[]{
             activeChar
           };
     
    }
   
    // Get the target type of the skill
    // (ex : ONE, SELF, HOLY, PET, AURA, AURA_CLOSE, AREA, MULTIFACE, PARTY, CLAN, CORPSE_PLAYER, CORPSE_MOB, CORPSE_CLAN, UNLOCKABLE, ITEM, UNDEAD)
    SkillTargetType targetType = getTargetType();

    // Get the type of the skill
    // (ex : PDAM, MDAM, DOT, BLEED, POISON, HEAL, HOT, MANAHEAL, MANARECHARGE, AGGDAMAGE, BUFF, DEBUFF, STUN, ROOT, RESURRECT, PASSIVE...)
    SkillType skillType = getSkillType();

    switch(targetType)
    {
    // The skill can only be used on the L2Character targeted, or on the caster itself
      case TARGET_ONE:
      {
        boolean canTargetSelf = false;
        switch (skillType)
        {
          case BUFF:
          case HEAL:
          case HOT:
          case HEAL_PERCENT:
          case MANARECHARGE:
          case MANAHEAL:
          case NEGATE:
          case REFLECT:
          case UNBLEED:
          case UNPOISON: // case CANCEL:
          case SEED:
          case CPHEAL_PERCENT:
          case COMBATPOINTHEAL:
          case COMBATPOINTPERCENTHEAL:
          case MAGE_BANE:
          case WARRIOR_BANE:
          case BETRAY:
          case BALANCE_LIFE:
          case FORCE_BUFF:
            canTargetSelf = true;
            break;
        }
       
        switch (skillType)
        {
          case CONFUSION:
          case DEBUFF:
          case STUN:
          case ROOT:
          case FEAR:
          case SLEEP:
          case MUTE:
          case WEAKNESS:
          case PARALYZE:
          case CANCEL:
          case MAGE_BANE:
          case WARRIOR_BANE:
            if (checkPartyClan(activeChar, target))
            {
              activeChar.sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
              return null;
            }
            break;
        }
       
        switch (skillType)
        {
          case AGGDEBUFF:
          case DEBUFF:
          case BLEED:
          case CONFUSION:
          case FEAR:
          case PARALYZE:
          case SLEEP:
          case ROOT:
          case WEAKNESS:
          case MUTE:
          case CANCEL:
          case DOT:
          case POISON:
          case AGGREDUCE_CHAR:
          case AGGDAMAGE:
          case AGGREMOVE:
          case MANADAM:
            // Like L2OFF if the skills is TARGET_ONE (skillType) can't be used on Npc
            if (target instanceof L2NpcInstance && !(target instanceof L2MonsterInstance))
            {
              activeChar.sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
              return null;
            }
            break;
        }
       
        // Like L2OFF Shield stun can't be used on Npc
        if (getId() == 92 && target instanceof L2NpcInstance && !(target instanceof L2MonsterInstance))
        {
          activeChar.sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
          return null;
        }
       
        // Check for null target or any other invalid target
        if (target == null || target.isDead() || target == activeChar && !canTargetSelf)
        {
          activeChar.sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
          return null;
        }
       
        // If a target is found, return it in a table else send a system message TARGET_IS_INCORRECT
        return new L2Character[]
        {
          target
        };
      }
      case TARGET_SELF:
      case TARGET_GROUND:
      {
        return new L2Character[]
        {
          activeChar
        };
      }
      case TARGET_HOLY:
      {
        if(activeChar instanceof L2PcInstance)
        {
          if(activeChar.getTarget() instanceof L2ArtefactInstance)
            return new L2Character[]
            {
              (L2ArtefactInstance) activeChar.getTarget()
            };
        }

        return null;
      }

      case TARGET_PET:
      {
        target = activeChar.getPet();
        if(target != null && !target.isDead())
          return new L2Character[]
          {
            target
          };

        return null;
      }
      case TARGET_OWNER_PET:
      {
        if(activeChar instanceof L2Summon)
        {
          target = ((L2Summon) activeChar).getOwner();
          if(target != null && !target.isDead())
            return new L2Character[]
            {
              target
            };
        }

        return null;
      }
      case TARGET_CORPSE_PET:
      {
        if(activeChar instanceof L2PcInstance)
        {
          target = activeChar.getPet();
          if(target != null && target.isDead())
            return new L2Character[]
            {
              target
            };
        }

        return null;
      }
      case TARGET_AURA:
      {
        int radius = getSkillRadius();
        boolean srcInArena = activeChar.isInsideZone(L2Character.ZONE_PVP) && !activeChar.isInsideZone(L2Character.ZONE_SIEGE);

        L2PcInstance src = null;
        if(activeChar instanceof L2PcInstance)
        {
          src = (L2PcInstance) activeChar;
        }

        if(activeChar instanceof L2Summon)
        {
          src = ((L2Summon) activeChar).getOwner();
        }

        // Go through the L2Character _knownList
        for(L2Object obj : activeChar.getKnownList().getKnownCharactersInRadius(radius))
        {
          if(obj == null || !(activeChar instanceof L2PlayableInstance) && !(obj instanceof L2PlayableInstance))
            continue;
         
          // Like L2OFF you can cast the skill on peace zone but hasn't any effect
          if(isOffensive() && L2Character.isInsidePeaceZone(target, activeChar))
            continue;
           
          if(src != null && (obj instanceof L2Attackable || obj instanceof L2PlayableInstance))
          {
            // Don't add this target if this is a Pc->Pc pvp casting and pvp condition not met
            if(obj == activeChar || obj == src)
            {
              continue;
            }
           
            if(!GeoData.getInstance().canSeeTarget(activeChar, obj))
            {
              continue;
            }

            // check if both attacker and target are L2PcInstances and if they are in same party
            if(obj instanceof L2PcInstance)
            {
              if(((L2PcInstance) obj).isDead())
              {
                continue;
              }

              if(((L2PcInstance) obj).getAppearance().getInvisible())
              {
                continue;
              }

              if(!src.checkPvpSkill(obj, this))
              {
                continue;
              }

              /*
              if(src.isInOlympiadMode() && !src.isOlympiadStart())
              {
                continue;
              }

             
              if(src.getParty() != null && ((L2PcInstance) obj).getParty() != null && src.getParty().getPartyLeaderOID() == ((L2PcInstance) obj).getParty().getPartyLeaderOID())
              {
                continue;
              }
              */

              if(!srcInArena && !(((L2Character) obj).isInsideZone(L2Character.ZONE_PVP) && !((L2Character) obj).isInsideZone(L2Character.ZONE_SIEGE)))
              {
                if(checkPartyClan(src, obj))
                {
                  continue;
                }
               
                /*if(src.getClanId() != 0 && src.getClanId() == ((L2PcInstance) obj).getClanId())
                {
                  continue;
                }*/
               
                if(src.getAllyId() != 0 && src.getAllyId() == ((L2PcInstance) obj).getAllyId())
                {
                  continue;
                }
              }
            }
            if(obj instanceof L2Summon)
            {
              L2PcInstance trg = ((L2Summon) obj).getOwner();
              if(trg == src)
              {
                continue;
              }

              if(!src.checkPvpSkill(trg, this))
              {
                continue;
              }

              /*
              if(src.isInOlympiadMode() && !src.isOlympiadStart())
              {
                continue;
              }
               */
             
              if(src.getParty() != null && trg.getParty() != null && src.getParty().getPartyLeaderOID() == trg.getParty().getPartyLeaderOID())
              {
                continue;
              }
             

              if(!srcInArena && !(((L2Character) obj).isInsideZone(L2Character.ZONE_PVP) && !((L2Character) obj).isInsideZone(L2Character.ZONE_SIEGE)))
              {
                /*if(src.getClanId() != 0 && src.getClanId() == trg.getClanId())
                {
                  continue;
                }*/
                if(checkPartyClan(src, obj))
                {
                  continue;
                }
               
                if(src.getAllyId() != 0 && src.getAllyId() == trg.getAllyId())
                {
                  continue;
                }
              }

              trg = null;
            }
          }
         
          if(!Util.checkIfInRange(radius, activeChar, obj, true))
          {
            continue;
          }

          if(!onlyFirst)
          {
            targetList.add((L2Character) obj);
          }
          else
            return new L2Character[]
            {
              (L2Character) obj
            };
         
        }

        src = null;

        return targetList.toArray(new L2Character[targetList.size()]);
      }
      case TARGET_AREA:
      {
        // Like L2OFF players can use TARGET_AREA skills on NPC in peacezone
        if(!(target instanceof L2Attackable || target instanceof L2PlayableInstance || target instanceof L2NpcInstance) || //   Target is not L2Attackable or L2PlayableInstance or L2NpcInstance
        getCastRange() >= 0 && (target == activeChar || target.isAlikeDead())) //target is null or self or dead/faking
        {
          activeChar.sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
          return null;
        }

        L2Character cha;

        if(getCastRange() >= 0)
        {
          cha = target;

          if(!onlyFirst)
          {
            targetList.add(cha); // Add target to target list
          }
          else
            return new L2Character[]
            {
              cha
            };
        }
        else
        {
          cha = activeChar;
        }

        boolean effectOriginIsL2PlayableInstance = cha instanceof L2PlayableInstance;

        L2PcInstance src = null;
        if(activeChar instanceof L2PcInstance)
        {
          src = (L2PcInstance) activeChar;
        }
        else if(activeChar instanceof L2Summon)
        {
          src = ((L2Summon) activeChar).getOwner();
        }

        int radius = getSkillRadius();

        boolean srcInArena = activeChar.isInsideZone(L2Character.ZONE_PVP) && !activeChar.isInsideZone(L2Character.ZONE_SIEGE);

        for(L2Object obj : activeChar.getKnownList().getKnownObjects().values())
        {
          if(obj == null || !(activeChar instanceof L2PlayableInstance) && !(obj instanceof L2PlayableInstance))
            continue;
           
         
          if(!(obj instanceof L2Attackable || obj instanceof L2PlayableInstance))
          {
            continue;
          }
          if(obj == cha)
          {
            continue;
          }
         
          if(src!=null && !src.checkPvpSkill(obj, this))
          {
            continue;
          }

          target = (L2Character) obj;

          if(!GeoData.getInstance().canSeeTarget(activeChar, target))
          {
            continue;
          }

          if(isOffensive()
            && L2Character.isInsidePeaceZone(activeChar, target))
          {
            continue;
          }
         
          if(!target.isAlikeDead() && target != activeChar)
          {
            if(!Util.checkIfInRange(radius, obj, cha, true))
            {
              continue;
            }

            if(src != null) // caster is l2playableinstance and exists
            {
              //check for Events
              if(obj instanceof L2PcInstance){
               
                L2PcInstance trg = (L2PcInstance) obj;
                if(trg == src)
                {
                  continue;
                }
               
                //if src is in event and trg not OR viceversa:
                //to be fixed for mixed events status (in TvT joining phase, someone can attack a partecipating CTF player with area attack)
                if( ((src._inEvent || src._inEventCTF || src._inEventDM || src._inEventTvT || src._inEventVIP) && (!trg._inEvent && !trg._inEventCTF && !trg._inEventDM && !trg._inEventTvT && !trg._inEventVIP)) || ((trg._inEvent || trg._inEventCTF || trg._inEventDM || trg._inEventTvT || trg._inEventVIP) && (!src._inEvent && !src._inEventCTF && !src._inEventDM && !src._inEventTvT && !src._inEventVIP))  ){
                  continue;
                }
               
              }else if(obj instanceof L2Summon){
               
                L2PcInstance trg = ((L2Summon) obj).getOwner();
                if(trg == src)
                {
                  continue;
                }
               
                //if src is in event and trg not OR viceversa:
                //to be fixed for mixed events status (in TvT joining phase, someone can attack a partecipating CTF player with area attack)
                if( ((src._inEvent || src._inEventCTF || src._inEventDM || src._inEventTvT || src._inEventVIP) && (!trg._inEvent && !trg._inEventCTF && !trg._inEventDM && !trg._inEventTvT && !trg._inEventVIP)) || ((trg._inEvent || trg._inEventCTF || trg._inEventDM || trg._inEventTvT || trg._inEventVIP) && (!src._inEvent && !src._inEventCTF && !src._inEventDM && !src._inEventTvT && !src._inEventVIP))  ){
                  continue;
                }
               
              }

              if(obj instanceof L2PcInstance)
              {
                L2PcInstance trg = (L2PcInstance) obj;
                if(trg == src)
                {
                  continue;
                }

                if(((L2PcInstance) obj).getAppearance().getInvisible())
                {
                  continue;
                }

                if(src.getParty() != null && trg.getParty() != null && src.getParty().getPartyLeaderOID() == trg.getParty().getPartyLeaderOID())
                {
                  continue;
                }
               
                if(!srcInArena && !(trg.isInsideZone(L2Character.ZONE_PVP) && !trg.isInsideZone(L2Character.ZONE_SIEGE)))
                {
                  if(src.getAllyId() == trg.getAllyId() && src.getAllyId() != 0)
                  {
                    continue;
                  }
                 
                  if(checkPartyClan(src, obj))
                  {
                    continue;
                  }
                  /*
                  if(src.getClan() != null && trg.getClan() != null)
                  {
                    if(src.getClan().getClanId() == trg.getClan().getClanId())
                    {
                      continue;
                    }
                  }
                  */

                  if(!src.checkPvpSkill(obj, this))
                  {
                    continue;
                  }
                }

                trg = null;
              }
              if(obj instanceof L2Summon)
              {
                L2PcInstance trg = ((L2Summon) obj).getOwner();
                if(trg == src)
                {
                  continue;
                }

                if(src.getParty() != null && trg.getParty() != null && src.getParty().getPartyLeaderOID() == trg.getParty().getPartyLeaderOID())
                {
                  continue;
                }

                if(!srcInArena && !(trg.isInsideZone(L2Character.ZONE_PVP) && !trg.isInsideZone(L2Character.ZONE_SIEGE)))
                {
                  if(src.getAllyId() == trg.getAllyId() && src.getAllyId() != 0)
                  {
                    continue;
                  }

                  /*
                  if(src.getClan() != null && trg.getClan() != null)
                  {
                    if(src.getClan().getClanId() == trg.getClan().getClanId())
                    {
                      continue;
                    }
                  }*/
                  if(checkPartyClan(src, obj))
                  {
                    continue;
                  }

                  if(!src.checkPvpSkill(trg, this))
                  {
                    continue;
                  }
                }

                trg = null;
              }
            }
            else
            // Skill user is not L2PlayableInstance
            {
              if(effectOriginIsL2PlayableInstance && // If effect starts at L2PlayableInstance and
              !(obj instanceof L2PlayableInstance))
              {
                continue;
              }
            }

            targetList.add((L2Character) obj);
          }
        }

        if(targetList.size() == 0)
          return null;

        src = null;

        return targetList.toArray(new L2Character[targetList.size()]);
      }
      case TARGET_MULTIFACE:
      {
        if(!(target instanceof L2Attackable) && !(target instanceof L2PcInstance))
        {
          activeChar.sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
          return null;
        }

        if(!onlyFirst)
        {
          targetList.add(target);
        }
        else
          return new L2Character[]
          {
            target
          };

        int radius = getSkillRadius();

        L2PcInstance src = null;
        if(activeChar instanceof L2PcInstance)
        {
          src = (L2PcInstance) activeChar;
        }
        else if(activeChar instanceof L2Summon)
        {
          src = ((L2Summon) activeChar).getOwner();
        }
       
        for(L2Object obj : activeChar.getKnownList().getKnownObjects().values())
        {
          if(obj == null)
          {
            continue;
          }

          if(!Util.checkIfInRange(radius, activeChar, obj, true))
          {
            continue;
          }

          //check for Events
          if(src!=null)
            if(obj instanceof L2PcInstance){
             
              L2PcInstance trg = (L2PcInstance) obj;
              if(trg == src)
              {
                continue;
              }
             
              //if src is in event and trg not OR viceversa:
              //to be fixed for mixed events status (in TvT joining phase, someone can attack a partecipating CTF player with area attack)
              if(((src._inEvent || src._inEventCTF || src._inEventDM || src._inEventTvT || src._inEventVIP) && (!trg._inEvent && !trg._inEventCTF && !trg._inEventDM && !trg._inEventTvT && !trg._inEventVIP)) || ((trg._inEvent || trg._inEventCTF || trg._inEventDM || trg._inEventTvT || trg._inEventVIP) && (!src._inEvent && !src._inEventCTF && !src._inEventDM && !src._inEventTvT && !src._inEventVIP))  ){
                continue;
              }
             
            }else if(obj instanceof L2Summon){
             
              L2PcInstance trg = ((L2Summon) obj).getOwner();
              if(trg == src)
              {
                continue;
              }
             
              //if src is in event and trg not OR viceversa:
              //to be fixed for mixed events status (in TvT joining phase, someone can attack a partecipating CTF player with area attack)
              if( ((src._inEvent || src._inEventCTF || src._inEventDM || src._inEventTvT || src._inEventVIP) && (!trg._inEvent && !trg._inEventCTF && !trg._inEventDM && !trg._inEventTvT && !trg._inEventVIP)) || ((trg._inEvent || trg._inEventCTF || trg._inEventDM || trg._inEventTvT || trg._inEventVIP) && (!src._inEvent && !src._inEventCTF && !src._inEventDM && !src._inEventTvT && !src._inEventVIP))  ){
                continue;
              }
             
            }
         
          if(obj instanceof L2Attackable && obj != target)
          {
            targetList.add((L2Character) obj);
          }

          if(targetList.size() == 0)
          {
            activeChar.sendPacket(new SystemMessage(SystemMessageId.TARGET_CANT_FOUND));
            return null;
          }
        }
        return targetList.toArray(new L2Character[targetList.size()]);
        //TODO multiface targets all around right now.  need it to just get targets
        //the character is facing.
      }
      case TARGET_PARTY:
      {
        if(onlyFirst)
          return new L2Character[]
          {
            activeChar
          };

        targetList.add(activeChar);

        L2PcInstance player = activeChar.getActingPlayer();
        if (player == null)
        {
          return new L2Character[] { activeChar };
        }
       
        if(activeChar instanceof L2Summon)
        {
          targetList.add(player);
        }
        else if(activeChar instanceof L2PcInstance)
        {
          if(player.getPet() != null)
          {
            targetList.add(player.getPet());
          }
        }

        if(activeChar.getParty() != null)
        {
          // Get all visible objects in a spheric area near the L2Character
          // Get a list of Party Members
          List<L2PcInstance> partyList = activeChar.getParty().getPartyMembers();

          for(L2PcInstance partyMember : partyList)
          {
            if(partyMember == null)
            {
              continue;
            }
            if(partyMember == player)
            {
              continue;
            }

            //check if allow interference is allowed if player is not on event but target is on event
            //if(((TvT._started && !Config.TVT_ALLOW_INTERFERENCE) || (CTF._started && !Config.CTF_ALLOW_INTERFERENCE) || (DM._started && !Config.DM_ALLOW_INTERFERENCE)) && !player.isGM())
            if(((TvT.is_started() && !Config.TVT_ALLOW_INTERFERENCE) || (CTF.is_started() && !Config.CTF_ALLOW_INTERFERENCE) || (DM.is_started() && !Config.DM_ALLOW_INTERFERENCE))/* && !player.isGM()*/)
            {
              if((partyMember._inEventTvT && !player._inEventTvT) || (!partyMember._inEventTvT && player._inEventTvT))
              {
                continue;
              }
              if((partyMember._inEventCTF && !player._inEventCTF) || (!partyMember._inEventCTF && player._inEventCTF))
              {
                continue;
              }
              if((partyMember._inEventDM && !player._inEventDM) || (!partyMember._inEventDM && player._inEventDM))
              {
                continue;
              }
            }

            if(!partyMember.isDead() && Util.checkIfInRange(getSkillRadius(), activeChar, partyMember, true))
            {
              L2PcInstance src = null;
              if(activeChar instanceof L2PcInstance)
              {
                src = (L2PcInstance) activeChar;
              }
              else if(activeChar instanceof L2Summon)
              {
                src = ((L2Summon) activeChar).getOwner();
              }
             
              L2PcInstance trg = partyMember;
             
              //if src is in event and trg not OR viceversa:
              //to be fixed for mixed events status (in TvT joining phase, someone can attack a partecipating CTF player with area attack)
              if(src!= null)
                if( ((src._inEvent || src._inEventCTF || src._inEventDM || src._inEventTvT || src._inEventVIP) && (!trg._inEvent && !trg._inEventCTF && !trg._inEventDM && !trg._inEventTvT && !trg._inEventVIP)) || ((trg._inEvent || trg._inEventCTF || trg._inEventDM || trg._inEventTvT || trg._inEventVIP) && (!src._inEvent && !src._inEventCTF && !src._inEventDM && !src._inEventTvT && !src._inEventVIP))  ){
                  continue;
                }
             
              targetList.add(partyMember);

              if(partyMember.getPet() != null && !partyMember.getPet().isDead())
              {
                targetList.add(partyMember.getPet());
              }
            }
          }

          partyList = null;
        }

        player = null;

        return targetList.toArray(new L2Character[targetList.size()]);
      }
      case TARGET_PARTY_MEMBER:
      {
        if(target != null && !target.isDead() && (
            target == activeChar
            || (activeChar.getParty() != null
              && target.getParty() != null
              && activeChar.getParty().getPartyLeaderOID() == target.getParty().getPartyLeaderOID())
            || (activeChar.getPet() == target)
            || (activeChar == target.getPet())))
        {
          // If a target is found, return it in a table else send a system message TARGET_IS_INCORRECT
          return new L2Character[]
          {
            target
          };
         
        }
        activeChar.sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
        return null;
      }
      case TARGET_PARTY_OTHER:
      {
        if(target != activeChar && target != null && !target.isDead()
            && activeChar.getParty() != null
            && target.getParty() != null
            && activeChar.getParty().getPartyLeaderOID() == target.getParty().getPartyLeaderOID())
        {
          // If a target is found, return it in a table else send a system message TARGET_IS_INCORRECT
          return new L2Character[]
          {
            target
          };
        }
        activeChar.sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
        return null;
      }
      case TARGET_CORPSE_ALLY:
      case TARGET_ALLY:
      {
        if(activeChar instanceof L2PcInstance)
        {
         
          int radius = getSkillRadius();
          L2PcInstance player = (L2PcInstance) activeChar;
          L2Clan clan = player.getClan();

         
          if(targetType != SkillTargetType.TARGET_CORPSE_ALLY) //if corpose, the caster is not included
          {
            if(player.isInOlympiadMode())
              return new L2Character[]
              {
                player
              };
           
            if(!onlyFirst)
            {
              targetList.add(player);
            }
            else
              return new L2Character[]
              {
                player
              };
          }

          L2PcInstance src = null;
          if(activeChar instanceof L2PcInstance)
          {
            src = (L2PcInstance) activeChar;
          }
          else if(activeChar instanceof L2Summon)
          {
            src = ((L2Summon) activeChar).getOwner();
          }
         
          if(clan != null)
          {
            // Get all visible objects in a spheric area near the L2Character
            // Get Clan Members
            for(L2Object newTarget : activeChar.getKnownList().getKnownObjects().values())
            {
              if(newTarget == null || !(newTarget instanceof L2PcInstance))
              {
                continue;
              }

              L2PcInstance playerTarget = (L2PcInstance) newTarget;
             
              if(playerTarget.isDead() && targetType != SkillTargetType.TARGET_CORPSE_ALLY){
               
                continue;
               
              }
             
              //if ally is different --> clan is different too, so --> continue
              if(player.getAllyId() != 0){
               
                if(playerTarget.getAllyId() != player.getAllyId())
                  continue;
               
              }else{ //check if clan is not the same --> continue
               
                if(player.getClanId() != playerTarget.getClanId())
                  continue;
               
              }
             
              //check for Events
              if(src!= null){
               
                if(playerTarget == src)
                {
                  continue;
                }
               
                //if src is in event and trg not OR viceversa:
                //to be fixed for mixed events status (in TvT joining phase, someone can attack a partecipating CTF player with area attack)
                if( ((src._inEvent
                    || src._inEventCTF
                    || src._inEventDM
                    || src._inEventTvT
                    || src._inEventVIP)
                    && (!playerTarget._inEvent
                        && !playerTarget._inEventCTF
                        && !playerTarget._inEventDM
                        && !playerTarget._inEventTvT
                        && !playerTarget._inEventVIP))
                        || ((playerTarget._inEvent
                            || playerTarget._inEventCTF
                            || playerTarget._inEventDM
                            || playerTarget._inEventTvT
                            || playerTarget._inEventVIP)
                            && (!src._inEvent
                                && !src._inEventCTF
                                && !src._inEventDM
                                && !src._inEventTvT
                                && !src._inEventVIP))  ){
                  continue;
                }
               
              }
             
              /* The target_ally or target_corpse_ally have to work indipendent on duel/party status
              if(player.isInDuel()
                  && (player.getDuelId() != ((L2PcInstance) newTarget).getDuelId()
                  || player.getParty() != null
                  && !player.getParty().getPartyMembers().contains(newTarget)))
              {
                continue;
              }
              */
             
             
             
                 
                /*}else if(newTarget instanceof L2Summon){
                 
                  L2PcInstance trg = ((L2Summon) newTarget).getOwner();
                  if(trg == src)
                  {
                    continue;
                  }
                 
                  //if src is in event and trg not OR viceversa:
                  //to be fixed for mixed events status (in TvT joining phase, someone can attack a partecipating CTF player with area attack)
                  if( ((src._inEvent || src._inEventCTF || src._inEventDM || src._inEventTvT || src._inEventVIP) && (!trg._inEvent && !trg._inEventCTF && !trg._inEventDM && !trg._inEventTvT && !trg._inEventVIP)) || ((trg._inEvent || trg._inEventCTF || trg._inEventDM || trg._inEventTvT || trg._inEventVIP) && (!src._inEvent && !src._inEventCTF && !src._inEventDM && !src._inEventTvT && !src._inEventVIP))  ){
                    continue;
                  }
                 
                }
                */

              L2Summon pet = ((L2PcInstance) newTarget).getPet();
              if(pet != null && Util.checkIfInRange(radius, activeChar, pet, true) && !onlyFirst && (targetType == SkillTargetType.TARGET_CORPSE_ALLY && pet.isDead() || targetType == SkillTargetType.TARGET_ALLY && !pet.isDead()) && player.checkPvpSkill(newTarget, this))
              {
                targetList.add(pet);
              }
              pet = null;

              if(targetType == SkillTargetType.TARGET_CORPSE_ALLY)
              {
                if(!((L2PcInstance) newTarget).isDead())
                {
                  continue;
                }

                if(getSkillType() == SkillType.RESURRECT && ((L2PcInstance) newTarget).isInsideZone(L2Character.ZONE_SIEGE))
                {
                  continue;
                }
              }

              if(!Util.checkIfInRange(radius, activeChar, newTarget, true))
              {
                continue;
              }

              // Don't add this target if this is a Pc->Pc pvp casting and pvp condition not met
              if(!player.checkPvpSkill(newTarget, this))
              {
                continue;
              }

              if(!onlyFirst)
              {
                targetList.add((L2Character) newTarget);
              }
              else
                return new L2Character[]
                {
                  (L2Character) newTarget
                };

            }
          }

          player = null;
          clan = null;
        }
        return targetList.toArray(new L2Character[targetList.size()]);
      }
      case TARGET_CORPSE_CLAN:
      case TARGET_CLAN:
      {
        if(activeChar instanceof L2PcInstance)
        {
          int radius = getSkillRadius();
          L2PcInstance player = (L2PcInstance) activeChar;
          L2Clan clan = player.getClan();

          if(targetType != SkillTargetType.TARGET_CORPSE_CLAN)
          {
            if(player.isInOlympiadMode())
              return new L2Character[]
              {
                player
              };
           
            if(!onlyFirst)
            {
              targetList.add(player);
            }
            else
              return new L2Character[]
              {
                player
              };
          }

          if(clan != null)
          {
            // Get all visible objects in a spheric area near the L2Character
            // Get Clan Members
            for(L2ClanMember member : clan.getMembers())
            {
              L2PcInstance newTarget = member.getPlayerInstance();

              if(newTarget == null || newTarget == player)
              {
                continue;
              }

              if(player.isInDuel() && (player.getDuelId() != newTarget.getDuelId() || player.getParty() == null && player.getParty() != newTarget.getParty()))
              {
                continue;
              }
             
              L2PcInstance trg = newTarget;
              L2PcInstance src = player;

              //if src is in event and trg not OR viceversa:
              //to be fixed for mixed events status (in TvT joining phase, someone can attack a partecipating CTF player with area attack)
                if( ((src._inEvent || src._inEventCTF || src._inEventDM || src._inEventTvT || src._inEventVIP) && (!trg._inEvent && !trg._inEventCTF && !trg._inEventDM && !trg._inEventTvT && !trg._inEventVIP)) || ((trg._inEvent || trg._inEventCTF || trg._inEventDM || trg._inEventTvT || trg._inEventVIP) && (!src._inEvent && !src._inEventCTF && !src._inEventDM && !src._inEventTvT && !src._inEventVIP))  ){
                  continue;
                }

             
              /*
              //check if allow interference is allowed if player is not on event but target is on event
              //if(((TvT._started && !Config.TVT_ALLOW_INTERFERENCE) || (CTF._started && !Config.CTF_ALLOW_INTERFERENCE) || (DM._started && !Config.DM_ALLOW_INTERFERENCE)) && !player.isGM())
              if(((TvT.is_inProgress() && !Config.TVT_ALLOW_INTERFERENCE) || (CTF.is_inProgress() && !Config.CTF_ALLOW_INTERFERENCE) || (DM.is_inProgress() && !Config.DM_ALLOW_INTERFERENCE)))
              {
                if((newTarget._inEventTvT && !player._inEventTvT) || (!newTarget._inEventTvT && player._inEventTvT))
                {
                  continue;
                }
                if((newTarget._inEventCTF && !player._inEventCTF) || (!newTarget._inEventCTF && player._inEventCTF))
                {
                  continue;
                }
                if((newTarget._inEventDM && !player._inEventDM) || (!newTarget._inEventDM && player._inEventDM))
                {
                  continue;
                }
              }
              */

              L2Summon pet = newTarget.getPet();
              if(pet != null && Util.checkIfInRange(radius, activeChar, pet, true) && !onlyFirst && (targetType == SkillTargetType.TARGET_CORPSE_CLAN && pet.isDead() || targetType == SkillTargetType.TARGET_CLAN && !pet.isDead()) && player.checkPvpSkill(newTarget, this))
              {
                targetList.add(pet);
              }

              pet = null;

              if(targetType == SkillTargetType.TARGET_CORPSE_CLAN)
              {
                if(!newTarget.isDead())
                {
                  continue;
                }

                if(getSkillType() == SkillType.RESURRECT)
                {
                  // check target is not in a active siege zone
                  Siege siege = SiegeManager.getInstance().getSiege(newTarget);
                  if(siege != null && siege.getIsInProgress())
                  {
                    continue;
                  }

                  siege = null;
                }
              }

              if(!Util.checkIfInRange(radius, activeChar, newTarget, true))
              {
                continue;
              }

              // Don't add this target if this is a Pc->Pc pvp casting and pvp condition not met
              if(!player.checkPvpSkill(newTarget, this))
              {
                continue;
              }

              if(!onlyFirst)
              {
                targetList.add(newTarget);
              }
              else
                return new L2Character[]
                {
                  newTarget
                };

              newTarget = null;
            }
          }
       
          player = null;
          clan = null;
        }       
        else if (activeChar instanceof L2NpcInstance)
        {
          // for buff purposes, returns friendly mobs nearby and mob itself
          final L2NpcInstance npc = (L2NpcInstance) activeChar;
          if (npc.getFactionId() == null || npc.getFactionId().isEmpty())
          {
            return new L2Character[]{activeChar};
          }
          targetList.add(activeChar);
          final Collection<L2Object> objs = activeChar.getKnownList().getKnownObjects().values();
          //synchronized (activeChar.getKnownList().getKnownObjects())
          {
            for (L2Object newTarget : objs)
            {
              if (newTarget instanceof L2NpcInstance
                  && npc.getFactionId().equals(((L2NpcInstance) newTarget).getFactionId()))
              {
                if (!Util.checkIfInRange(getCastRange(), activeChar, newTarget, true))
                  continue;
                targetList.add((L2NpcInstance) newTarget);
              }
            }
          }
        }

        return targetList.toArray(new L2Character[targetList.size()]);
      }
      case TARGET_CORPSE_PLAYER:
      {
        if(target != null && target.isDead())
        {
          L2PcInstance player = null;

          if(activeChar instanceof L2PcInstance)
          {
            player = (L2PcInstance) activeChar;
          }

          L2PcInstance targetPlayer = null;

          if(target instanceof L2PcInstance)
          {
            targetPlayer = (L2PcInstance) target;
          }

          L2PetInstance targetPet = null;

          if(target instanceof L2PetInstance)
          {
            targetPet = (L2PetInstance) target;
          }

          if(player != null && (targetPlayer != null || targetPet != null))
          {
            boolean condGood = true;

            if(getSkillType() == SkillType.RESURRECT)
            {
              // check target is not in a active siege zone
              if(target.isInsideZone(L2Character.ZONE_SIEGE))
              {
                condGood = false;
                player.sendPacket(new SystemMessage(SystemMessageId.CANNOT_BE_RESURRECTED_DURING_SIEGE));
              }

              if(targetPlayer != null)
              {
                if(targetPlayer.isReviveRequested())
                {
                  if(targetPlayer.isRevivingPet())
                  {
                    player.sendPacket(new SystemMessage(SystemMessageId.MASTER_CANNOT_RES)); // While a pet is attempting to resurrect, it cannot help in resurrecting its master.
                  }
                  else
                  {
                    player.sendPacket(new SystemMessage(SystemMessageId.RES_HAS_ALREADY_BEEN_PROPOSED)); // Resurrection is already been proposed.
                  }
                  condGood = false;
                }
              }
              else if(targetPet != null)
              {
                if(targetPet.getOwner() != player)
                {
                  condGood = false;
                  player.sendMessage("You are not the owner of this pet");
                }
              }
            }

            if(condGood)
            {
              if(!onlyFirst)
              {
                targetList.add(target);
                return targetList.toArray(new L2Object[targetList.size()]);
              }
             
              return new L2Character[]
              {
                target
              };

            }
          }

          player = null;
          targetPlayer = null;
          targetPet = null;
        }
        activeChar.sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));

        return null;
      }
      case TARGET_CORPSE_MOB:
      {
        if(!(target instanceof L2Attackable) || !target.isDead())
        {
          activeChar.sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
          return null;
        }

        if(!onlyFirst)
        {
          targetList.add(target);
          return targetList.toArray(new L2Object[targetList.size()]);
        }
       
        return new L2Character[]
        {
          target
        };

      }
      case TARGET_AREA_CORPSE_MOB:
      {
        if(!(target instanceof L2Attackable) || !target.isDead())
        {
          activeChar.sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
          return null;
        }

        if(!onlyFirst)
        {
          targetList.add(target);
        }
        else
          return new L2Character[]
          {
            target
          };

        boolean srcInArena = activeChar.isInsideZone(L2Character.ZONE_PVP) && !activeChar.isInsideZone(L2Character.ZONE_SIEGE);
        L2PcInstance src = null;

        if(activeChar instanceof L2PcInstance)
        {
          src = (L2PcInstance) activeChar;
        }

        L2PcInstance trg = null;

        int radius = getSkillRadius();

        if(activeChar.getKnownList() != null)
        {
          for(L2Object obj : activeChar.getKnownList().getKnownObjects().values())
          {
            if(obj == null)
            {
              continue;
            }

            if(!(obj instanceof L2Attackable || obj instanceof L2PlayableInstance) || ((L2Character) obj).isDead() || (L2Character) obj == activeChar)
            {
              continue;
            }

            if(!Util.checkIfInRange(radius, target, obj, true))
            {
              continue;
            }

            if(!GeoData.getInstance().canSeeTarget(activeChar, obj))
            {
              continue;
            }
           
            if(isOffensive()
              && L2Character.isInsidePeaceZone(activeChar, obj))
            {
              continue;
            }

            if(obj instanceof L2PcInstance && src != null)
            {
              trg = (L2PcInstance) obj;

              if(src.getParty() != null && trg.getParty() != null && src.getParty().getPartyLeaderOID() == trg.getParty().getPartyLeaderOID())
              {
                continue;
              }

              if(!srcInArena && !(trg.isInsideZone(L2Character.ZONE_PVP) && !trg.isInsideZone(L2Character.ZONE_SIEGE)))
              {
                if(src.getAllyId() == trg.getAllyId() && src.getAllyId() != 0)
                {
                  continue;
                }

                if(src.getClan() != null && trg.getClan() != null)
                {
                  if(src.getClan().getClanId() == trg.getClan().getClanId())
                  {
                    continue;
                  }
                }

                if(!src.checkPvpSkill(obj, this))
                {
                  continue;
                }
              }
            }
            if(obj instanceof L2Summon && src != null)
            {
              trg = ((L2Summon) obj).getOwner();

              if(src.getParty() != null && trg.getParty() != null && src.getParty().getPartyLeaderOID() == trg.getParty().getPartyLeaderOID())
              {
                continue;
              }

              if(!srcInArena && !(trg.isInsideZone(L2Character.ZONE_PVP) && !trg.isInsideZone(L2Character.ZONE_SIEGE)))
              {
                if(src.getAllyId() == trg.getAllyId() && src.getAllyId() != 0)
                {
                  continue;
                }

                if(src.getClan() != null && trg.getClan() != null)
                {
                  if(src.getClan().getClanId() == trg.getClan().getClanId())
                  {
                    continue;
                  }
                }

                if(!src.checkPvpSkill(trg, this))
                {
                  continue;
                }
              }

            }

            //check for Events
            if(trg == src)
            {
              continue;
            }
           
            //if src is in event and trg not OR viceversa:
            //to be fixed for mixed events status (in TvT joining phase, someone can attack a partecipating CTF player with area attack)
            if(src!=null && trg!=null)
              if( ((src._inEvent || src._inEventCTF || src._inEventDM || src._inEventTvT || src._inEventVIP) && (!trg._inEvent && !trg._inEventCTF && !trg._inEventDM && !trg._inEventTvT && !trg._inEventVIP)) || ((trg._inEvent || trg._inEventCTF || trg._inEventDM || trg._inEventTvT || trg._inEventVIP) && (!src._inEvent && !src._inEventCTF && !src._inEventDM && !src._inEventTvT && !src._inEventVIP))  ){
                continue;
              }
           
            targetList.add((L2Character) obj);
          }
        }

        if(targetList.size() == 0)
          return null;

        trg = null;
        src = null;

        return targetList.toArray(new L2Character[targetList.size()]);
      }
      case TARGET_UNLOCKABLE:
      {
        if(!(target instanceof L2DoorInstance) && !(target instanceof L2ChestInstance))
        {
          // Like L2OFF if target isn't door or chest send message of incorrect target
          activeChar.sendPacket(new SystemMessage(SystemMessageId.INCORRECT_TARGET));
          return null;
        }
       
        if(!onlyFirst)
        {
          targetList.add(target);
          return targetList.toArray(new L2Object[targetList.size()]);
        }
       
        return new L2Character[]
        {
          target
        };

      }
      case TARGET_ITEM:
      {
        SystemMessage sm = new SystemMessage(SystemMessageId.S1_S2);
        sm.addString("Target type of skill is not currently handled");
        activeChar.sendPacket(sm);
        sm = null;
        return null;
      }
      case TARGET_UNDEAD:
      {
        if(target instanceof L2NpcInstance || target instanceof L2SummonInstance)
        {
          if(!target.isUndead() || target.isDead())
          {
            activeChar.sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
            return null;
          }

          if(!onlyFirst)
          {
            targetList.add(target);
          }
          else
            return new L2Character[]
            {
              target
            };

          return targetList.toArray(new L2Object[targetList.size()]);
        }
        activeChar.sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
        return null;
      }
      case TARGET_AREA_UNDEAD:
      {
        L2Character cha;

        int radius = getSkillRadius();

        if(getCastRange() >= 0 && (target instanceof L2NpcInstance || target instanceof L2SummonInstance) && target.isUndead() && !target.isAlikeDead())
        {
          cha = target;

          if(!onlyFirst)
          {
            targetList.add(cha); // Add target to target list
          }
          else
            return new L2Character[]
            {
              cha
            };

        }
        else
        {
          cha = activeChar;
        }

        if(cha != null && cha.getKnownList() != null)
        {
          for(L2Object obj : cha.getKnownList().getKnownObjects().values())
          {
            if(obj == null)
            {
              continue;
            }

            if(obj instanceof L2NpcInstance)
            {
              target = (L2NpcInstance) obj;
            }
            else if(obj instanceof L2SummonInstance)
            {
              target = (L2SummonInstance) obj;
            }
            else
            {
              continue;
            }

            if(!GeoData.getInstance().canSeeTarget(activeChar, target))
            {
              continue;
            }

            if(!target.isAlikeDead()) // If target is not dead/fake death and not self
            {
              if(!target.isUndead())
              {
                continue;
              }

              if(!Util.checkIfInRange(radius, cha, obj, true))
              {
                continue;
              }

              if(!onlyFirst)
              {
                targetList.add((L2Character) obj); // Add obj to target lists
              }
              else
                return new L2Character[]
                {
                  (L2Character) obj
                };
            }
          }
        }

        if(targetList.size() == 0)
          return null;

        cha = null;

        return targetList.toArray(new L2Character[targetList.size()]);
      }
      case TARGET_ENEMY_SUMMON:
      {
        if(target != null && target instanceof L2Summon)
        {
          L2Summon targetSummon = (L2Summon) target;
          if(activeChar instanceof L2PcInstance && activeChar.getPet() != targetSummon && !targetSummon.isDead() && (targetSummon.getOwner().getPvpFlag() != 0 || targetSummon.getOwner().getKarma() > 0 || targetSummon.getOwner().isInDuel()) || targetSummon.getOwner().isInsideZone(L2Character.ZONE_PVP) && ((L2PcInstance) activeChar).isInsideZone(L2Character.ZONE_PVP))
            return new L2Character[]
            {
              targetSummon
            };

          targetSummon = null;
        }
        return null;
      }
      case TARGET_SIEGE:
      {
        if(target != null && !target.isDead() && (target instanceof L2DoorInstance || target instanceof L2ControlTowerInstance))
          return new L2Character[]
          {
            target
          };
        return null;
      }
      case TARGET_TYRANNOSAURUS:
      {
        if(target instanceof L2PcInstance)
        {
          activeChar.sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
          return null;
        }
       
        if(target instanceof L2MonsterInstance && (((L2MonsterInstance) target).getNpcId() == 22217 || ((L2MonsterInstance) target).getNpcId() == 22216 || ((L2MonsterInstance) target).getNpcId() == 22215))
          return new L2Character[]
          {
            target
          };
        return null;
      }
      case TARGET_AREA_AIM_CORPSE:
      {
        if(target != null && target.isDead())
          return new L2Character[]
          {
            target
          };
        return null;
      }
      // npc only for now - untested
      case TARGET_CLAN_MEMBER:
      {
        if (activeChar instanceof L2NpcInstance)
        {
          // for buff purposes, returns friendly mobs nearby and mob itself
          final L2NpcInstance npc = (L2NpcInstance) activeChar;
          if (npc.getFactionId() == null || npc.getFactionId().isEmpty())
          {
            return new L2Character[]{activeChar};
          }
          final Collection<L2Object> objs = activeChar.getKnownList().getKnownObjects().values();
          for (L2Object newTarget : objs)
          {
            if (newTarget instanceof L2NpcInstance
                && npc.getFactionId().equals(((L2NpcInstance) newTarget).getFactionId()))
            {
              if (!Util.checkIfInRange(getCastRange(), activeChar, newTarget, true))
                continue;
              if (((L2NpcInstance) newTarget).getFirstEffect(this) != null)
                continue;
              targetList.add((L2NpcInstance) newTarget);
              break; // found
            }
          }
          if (targetList.isEmpty())
            targetList.add(npc);
        }
        return null;
      }
      default:
      {
        SystemMessage sm = new SystemMessage(SystemMessageId.S1_S2);
        sm.addString("Target type of skill is not currently handled");
        activeChar.sendPacket(sm);
        sm = null;
        return null;
      }
    }//end switch
  }

  public final L2Object[] getTargetList(L2Character activeChar)
  {
    return getTargetList(activeChar, false);
  }

  public final L2Object getFirstOfTargetList(L2Character activeChar)
  {
    L2Object[] targets;

    targets = getTargetList(activeChar, true);
    if(targets == null || targets.length == 0)
      return null;
    return targets[0];
  }

  public final Func[] getStatFuncs(L2Effect effect, L2Character player)
  {
    if(!(player instanceof L2PcInstance) && !(player instanceof L2Attackable) && !(player instanceof L2Summon))
      return _emptyFunctionSet;

    if(_funcTemplates == null)
      return _emptyFunctionSet;

    List<Func> funcs = new FastList<Func>();

    for(FuncTemplate t : _funcTemplates)
    {
      Env env = new Env();
      env.player = player;
      env.skill = this;
      Func f = t.getFunc(env, this); // skill is owner

      if(f != null)
      {
        funcs.add(f);
      }
    }
    if(funcs.size() == 0)
      return _emptyFunctionSet;

    return funcs.toArray(new Func[funcs.size()]);
  }

  public boolean hasEffects()
  {
    return _effectTemplates != null && _effectTemplates.length > 0;
  }

  public final L2Effect[] getEffects(L2Character effector, L2Character effected)
  {
    return this.getEffects(effector, effected, false, false, false);
  }
 
  public final L2Effect[] getEffects(L2Character effector, L2Character effected, boolean ss, boolean sps, boolean bss)
  {
    if (isPassive())
      return _emptyEffectSet;
   
    if (_effectTemplates == null)
      return _emptyEffectSet;
   
    if (effector != effected && effected.isInvul())
      return _emptyEffectSet;
   
    if (getSkillType() == SkillType.BUFF && effected.isBlockBuff())
      return _emptyEffectSet;
   
    List<L2Effect> effects = new FastList<L2Effect>();
   
    boolean skillMastery = false;
   
    if (!isToggle() && Formulas.getInstance().calcSkillMastery(effector))
    {
      skillMastery = true;
    }
   
    /*
     * if(getSkillType()==SkillType.BUFF) for(final L2Effect ef: effector.getAllEffects()) { if(ef!=null && ef.getSkill()!=null){ if(ef.getSkill().getId() == getId() && ef.getSkill().getLevel() > getLevel()) return _emptyEffectSet; } }
     */
   
    Env env = new Env();
    env.player = effector;
    env.target = effected;
    env.skill = this;
    env.skillMastery = skillMastery;
   
    for (EffectTemplate et : _effectTemplates)
    {
      boolean success = true;
      if (et.effectPower > -1)
        success = Formulas.calcEffectSuccess(effector, effected, et, this, ss, sps, bss);
     
      if (success)
      {
        L2Effect e = et.getEffect(env);
        if (e != null)
        {
          // e.scheduleEffect();
          effects.add(e);
        }
       
        e = null;     
      }
      /*
       * L2Effect e = et.getEffect(env); if(e != null) { effects.add(e); } e = null;
       */
    }
   
    if (effects.size() == 0)
      return _emptyEffectSet;
   
    return effects.toArray(new L2Effect[effects.size()]);
  }
 
  public final L2Effect[] getEffectsSelf(L2Character effector)
  {
    if(isPassive())
      return _emptyEffectSet;

    if(_effectTemplatesSelf == null)
      return _emptyEffectSet;

    List<L2Effect> effects = new FastList<L2Effect>();

    Env env = new Env();
    env.player = effector;
    env.target = effector;
    env.skill = this;
   
    for(EffectTemplate et : _effectTemplatesSelf)
    {
     
      L2Effect e = et.getEffect(env);
      if(e != null)
      {
        //Implements effect charge
        if(e.getEffectType() == L2Effect.EffectType.CHARGE)
        {
          env.skill = SkillTable.getInstance().getInfo(8, effector.getSkillLevel(8));
          EffectCharge effect = (EffectCharge) env.target.getFirstEffect(L2Effect.EffectType.CHARGE);
          if(effect != null)
          {
            int effectcharge = effect.getLevel();
            if(effectcharge < _numCharges)
            {
              effectcharge++;
              effect.addNumCharges(effectcharge);
              if(env.target instanceof L2PcInstance)
              {
                env.target.sendPacket(new EtcStatusUpdate((L2PcInstance) env.target));
                SystemMessage sm = new SystemMessage(SystemMessageId.FORCE_INCREASED_TO_S1);
                sm.addNumber(effectcharge);
                env.target.sendPacket(sm);
                sm = null;
              }
            }
          }
          else
          {
            effects.add(e);
          }
        }
        else
        {
          effects.add(e);
        }
      }

      e = null;
    }
    if(effects.size() == 0)
      return _emptyEffectSet;

    return effects.toArray(new L2Effect[effects.size()]);
  }

  public final void attach(FuncTemplate f)
  {
    if(_funcTemplates == null)
    {
      _funcTemplates = new FuncTemplate[]
      {
        f
      };
    }
    else
    {
      int len = _funcTemplates.length;
      FuncTemplate[] tmp = new FuncTemplate[len + 1];
      System.arraycopy(_funcTemplates, 0, tmp, 0, len);
      tmp[len] = f;
      _funcTemplates = tmp;
      tmp = null;
    }
  }

  public final void attach(EffectTemplate effect)
  {
    if(_effectTemplates == null)
    {
      _effectTemplates = new EffectTemplate[]
      {
        effect
      };
    }
    else
    {
      int len = _effectTemplates.length;
      EffectTemplate[] tmp = new EffectTemplate[len + 1];
      System.arraycopy(_effectTemplates, 0, tmp, 0, len);
      tmp[len] = effect;
      _effectTemplates = tmp;
      tmp = null;
    }
  }

  public final void attachSelf(EffectTemplate effect)
  {
    if(_effectTemplatesSelf == null)
    {
      _effectTemplatesSelf = new EffectTemplate[]
      {
        effect
      };
    }
    else
    {
      int len = _effectTemplatesSelf.length;
      EffectTemplate[] tmp = new EffectTemplate[len + 1];
      System.arraycopy(_effectTemplatesSelf, 0, tmp, 0, len);
      tmp[len] = effect;
      _effectTemplatesSelf = tmp;
      tmp = null;
    }
  }
 
  // Author Jose Moreira
  public boolean isAbnormalEffectByName(int abnormalEffect)
  {
    // Function to know if the skill has "abnormalEffect"
    if (isPassive())
      return false;
   
    if (_effectTemplates == null)
      return false;
   
    for (EffectTemplate et : _effectTemplates)
    {
      if (et.abnormalEffect == abnormalEffect)
      {
        return true;
      }
    }
    return false;
  }
 
  public final void attach(Condition c, boolean itemOrWeapon)
  {
    if(itemOrWeapon)
    {
      _itemPreCondition = c;
    }
    else
    {
      _preCondition = c;
    }
  }

  public boolean checkPartyClan(L2Character activeChar, L2Object target)
  {
    if(activeChar instanceof L2PcInstance && target instanceof L2PcInstance)
    {
      L2PcInstance targetChar = (L2PcInstance) target;
      L2PcInstance activeCh = (L2PcInstance) activeChar;

      if(activeCh.isInOlympiadMode() && activeCh.isOlympiadStart() && targetChar.isInOlympiadMode() && targetChar.isOlympiadStart())
        return false;

      if(activeCh.isInDuel() && targetChar.isInDuel() && activeCh.getDuelId() == targetChar.getDuelId())
        return false;
     
      //if src is in event and trg not OR viceversa, the target must be not attackable
      //to be fixed for mixed events status (in TvT joining phase, someone can attack a partecipating CTF player with area attack)
      if( ((activeCh._inEvent || activeCh._inEventCTF || activeCh._inEventDM || activeCh._inEventTvT || activeCh._inEventVIP) && (!targetChar._inEvent && !targetChar._inEventCTF && !targetChar._inEventDM && !targetChar._inEventTvT && !targetChar._inEventVIP)) || ((targetChar._inEvent || targetChar._inEventCTF || targetChar._inEventDM || targetChar._inEventTvT || targetChar._inEventVIP) && (!activeCh._inEvent && !activeCh._inEventCTF && !activeCh._inEventDM && !activeCh._inEventTvT && !activeCh._inEventVIP))  ){
        return true;
      }
     
      if((activeCh._inEvent && targetChar._inEvent) ||
          (activeCh._inEventDM && targetChar._inEventDM) ||
          (activeCh._inEventTvT && targetChar._inEventTvT) ||
          (activeCh._inEventCTF && targetChar._inEventCTF) ||
          (activeCh._inEventVIP && targetChar._inEventVIP)){
       
        return false;
      }

      if(activeCh.getParty() != null && targetChar.getParty() != null && //Is in the same party???
      activeCh.getParty().getPartyLeaderOID() == targetChar.getParty().getPartyLeaderOID())
        return true;
      if(activeCh.getClan() != null && targetChar.getClan() != null && //Is in the same clan???
      activeCh.getClan().getClanId() == targetChar.getClan().getClanId())
        return true;
      targetChar = null;
      activeCh = null;
    }
    return false;
  }

  @Override
  public String toString()
  {
    return "" + _name + "[id=" + _id + ",lvl=" + _level + "]";
  }
 
  /**
   * @return Returns the _targetConsumeId.
   */
  public final int getTargetConsumeId()
  {
    return _targetConsumeId;
  }
 
  /**
   * @return Returns the targetConsume.
   */
  public final int getTargetConsume()
  {
    return _targetConsume;
  }
 
  public boolean hasSelfEffects()
  {
    return (_effectTemplatesSelf != null && _effectTemplatesSelf.length > 0);
  }
 
  /**
   * @return minimum skill/effect land rate (default is 1).
   */
  public final int getMinChance()
  {
    return _minChance;
  }
 
  /**
   * @return maximum skill/effect land rate (default is 99).
   */
  public final int getMaxChance()
  {
    return _maxChance;
  }
 
  /**
   * @return the _advancedFlag
   */
  public boolean is_advancedFlag()
  {
    return _advancedFlag;
  }
 
  /**
   * @return the _advancedMultiplier
   */
  public int get_advancedMultiplier()
  {
    return _advancedMultiplier;
  }
}
TOP

Related Classes of com.l2jfrozen.gameserver.model.L2Skill

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.