Package l2p.gameserver.model

Source Code of l2p.gameserver.model.L2Playable

package l2p.gameserver.model;

import static l2p.gameserver.model.L2Zone.ZoneType.Siege;
import static l2p.gameserver.model.L2Zone.ZoneType.peace_zone;

import java.util.Map.Entry;

import l2p.Config;
import l2p.extensions.multilang.CustomMessage;
import l2p.gameserver.ai.CtrlEvent;
import l2p.gameserver.ai.CtrlIntention;
import l2p.gameserver.ai.DefaultAI;
import l2p.gameserver.cache.Msg;
import l2p.gameserver.geodata.GeoEngine;
import l2p.gameserver.instancemanager.SiegeManager;
import l2p.gameserver.model.L2Skill.SkillTargetType;
import l2p.gameserver.model.L2Skill.SkillType;
import l2p.gameserver.model.L2Zone.ZoneType;
import l2p.gameserver.model.entity.Duel;
import l2p.gameserver.model.entity.Duel.DuelState;
import l2p.gameserver.model.instances.L2NpcInstance;
import l2p.gameserver.model.instances.L2TerritoryFlagInstance;
import l2p.gameserver.model.items.Inventory;
import l2p.gameserver.model.items.L2ItemInstance;
import l2p.gameserver.model.quest.QuestState;
import l2p.gameserver.serverpackets.SystemMessage;
import l2p.gameserver.skills.Stats;
import l2p.gameserver.tables.SkillTable;
import l2p.gameserver.templates.L2CharTemplate;
import l2p.gameserver.templates.L2EtcItem;
import l2p.gameserver.templates.L2Weapon;
import l2p.gameserver.templates.L2Weapon.WeaponType;
import l2p.util.GArray;
import l2p.util.GCSArray;
import l2p.util.Rnd;

public abstract class L2Playable extends L2Character
{
  private byte _isSilentMoving;
  private long _checkAggroTimestamp = 0;

  public L2Playable(int objectId, L2CharTemplate template)
  {
    super(objectId, template);
  }

  public abstract Inventory getInventory();

  /**
   * Проверяет, выставлять ли PvP флаг для игрока.<BR><BR>
   */
  @Override
  public boolean checkPvP(final L2Character target, L2Skill skill)
  {
    L2Player player = getPlayer();
    if(isDead() || target == null || player == null || target == this || target == player || target == player.getPet() || player.getKarma() > 0)
    {
      return false;
    }
    if(skill != null)
    {
      if(skill.altUse())
      {
        return false;
      }
      if(skill.getSkillType().equals(SkillType.BEAST_FEED))
      {
        return false;
      }
      if(skill.getTargetType() == SkillTargetType.TARGET_UNLOCKABLE)
      {
        return false;
      }
      if(skill.getTargetType() == SkillTargetType.TARGET_CHEST)
      {
        return false;
      }
    }
    // Проверка на дуэли... Мэмбэры одной дуэли не флагаются
    if(getDuel() != null && getDuel() == target.getDuel())
    {
      return false;
    }
    if(isInZone(peace_zone) || target.isInZone(peace_zone) || isInZoneBattle() || target.isInZoneBattle())
    {
      return false;
    }
    if(isInZone(Siege) && target.isInZone(Siege))
    {
      return false;
    }
    if(skill == null || skill.isOffensive())
    {
      if(target.getKarma() > 0)
      {
        return false;
      }
      else if(target.isPlayable())
      {
        return true;
      }
    }
    else if(target.getPvpFlag() > 0 || target.getKarma() > 0 || target.isMonster())
    {
      return true;
    }
    return false;
  }

  /**
   * Проверяет, можно ли атаковать цель (для физ атак)
   */
  public boolean checkAttack(L2Character target)
  {
    L2Player player = getPlayer();
    if(player == null)
    {
      return false;
    }
    if(target == null || target.isDead())
    {
      player.sendPacket(Msg.INVALID_TARGET);
      return false;
    }
    if(!isInRange(target, 2000))
    {
      player.sendPacket(Msg.YOUR_TARGET_IS_OUT_OF_RANGE);
      return false;
    }
    if(target.isDoor() && !target.isAttackable(this))
    {
      player.sendPacket(Msg.INVALID_TARGET);
      return false;
    }
    if(target.paralizeOnAttack(player))
    {
      if(Config.PARALIZE_ON_RAID_DIFF)
      {
        paralizeMe(target);
      }
      return false;
    }
    if(!GeoEngine.canSeeTarget(this, target, false) || getReflection() != target.getReflection())
    {
      player.sendPacket(Msg.CANNOT_SEE_TARGET);
      return false;
    }
    // Запрет на атаку мирных NPC в осадной зоне на TW. Иначе таким способом набивают очки.
    if(player.getTerritorySiege() > -1 && target.isNpc() && !(target instanceof L2TerritoryFlagInstance) && !(target.getAI() instanceof DefaultAI) && player.isInZone(ZoneType.Siege))
    {
      player.sendPacket(Msg.INVALID_TARGET);
      return false;
    }
    if(target.isPlayable())
    {
      // Нельзя атаковать того, кто находится на арене, если ты сам не на арене
      if(isInZoneBattle() != target.isInZoneBattle())
      {
        player.sendPacket(Msg.INVALID_TARGET);
        return false;
      }
      // Если цель либо атакующий находится в мирной зоне - атаковать нельзя
      if((isInZonePeace() || target.isInZonePeace()) && !player.getPlayerAccess().PeaceAttack)
      {
        player.sendPacket(Msg.YOU_MAY_NOT_ATTACK_THIS_TARGET_IN_A_PEACEFUL_ZONE);
        return false;
      }
      if(player.isInOlympiadMode() && !player.isOlympiadCompStart())
      {
        return false;
      }
    }
    return true;
  }

  @Override
  public void doAttack(L2Character target)
  {
    L2Player player = getPlayer();
    if(player == null)
    {
      return;
    }
    if(isAMuted() || isAttackingNow())
    {
      player.sendActionFailed();
      return;
    }
    if(player.inObserverMode())
    {
      player.sendMessage(new CustomMessage("l2p.gameserver.model.L2Playable.OutOfControl.ObserverNoAttack", player));
      return;
    }
    if(!checkAttack(target))
    {
      getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE, null, null);
      player.sendActionFailed();
      return;
    }
    // Прерывать дуэли если цель не дуэлянт
    if(getDuel() != null)
    {
      if(target.getDuel() != getDuel())
      {
        getDuel().setDuelState(player.getStoredId(), DuelState.Interrupted);
      }
      else if(getDuel().getDuelState(player.getStoredId()) == DuelState.Interrupted)
      {
        player.sendPacket(Msg.INVALID_TARGET);
        return;
      }
    }
    L2Weapon weaponItem = getActiveWeaponItem();
    if(weaponItem != null && (weaponItem.getItemType() == WeaponType.BOW || weaponItem.getItemType() == WeaponType.CROSSBOW))
    {
      double bowMpConsume = weaponItem.getMpConsume();
      if(bowMpConsume > 0)
      {
        // cheap shot SA
        double chance = calcStat(Stats.MP_USE_BOW_CHANCE, 0., target, null);
        if(chance > 0 && Rnd.chance(chance))
        {
          bowMpConsume = calcStat(Stats.MP_USE_BOW, bowMpConsume, target, null);
        }
        if(_currentMp < bowMpConsume)
        {
          getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE, null, null);
          player.sendPacket(Msg.NOT_ENOUGH_MP);
          player.sendActionFailed();
          return;
        }
        reduceCurrentMp(bowMpConsume, null);
      }
      if(!player.checkAndEquipArrows())
      {
        getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE, null, null);
        player.sendPacket(player.getActiveWeaponInstance().getItemType() == WeaponType.BOW ? Msg.YOU_HAVE_RUN_OUT_OF_ARROWS : Msg.NOT_ENOUGH_BOLTS);
        player.sendActionFailed();
        return;
      }
    }
    super.doAttack(target);
  }

  private GCSArray<QuestState> _NotifyQuestOfDeathList;
  private GCSArray<QuestState> _NotifyQuestOfPlayerKillList;

  public void addNotifyQuestOfDeath(QuestState qs)
  {
    if(qs == null || _NotifyQuestOfDeathList != null && _NotifyQuestOfDeathList.contains(qs))
    {
      return;
    }
    if(_NotifyQuestOfDeathList == null)
    {
      _NotifyQuestOfDeathList = new GCSArray<QuestState>();
    }
    _NotifyQuestOfDeathList.add(qs);
  }

  public void addNotifyOfPlayerKill(QuestState qs)
  {
    if(qs == null || _NotifyQuestOfPlayerKillList != null && _NotifyQuestOfPlayerKillList.contains(qs))
    {
      return;
    }
    if(_NotifyQuestOfPlayerKillList == null)
    {
      _NotifyQuestOfPlayerKillList = new GCSArray<QuestState>();
    }
    _NotifyQuestOfPlayerKillList.add(qs);
  }

  public void removeNotifyOfPlayerKill(QuestState qs)
  {
    if(qs == null || _NotifyQuestOfPlayerKillList == null)
    {
      return;
    }
    _NotifyQuestOfPlayerKillList.remove(qs);
    if(_NotifyQuestOfPlayerKillList.isEmpty())
    {
      _NotifyQuestOfPlayerKillList = null;
    }
  }

  public GCSArray<QuestState> getNotifyOfPlayerKillList()
  {
    return _NotifyQuestOfPlayerKillList;
  }

  @Override
  public void doDie(L2Character killer)
  {
    super.doDie(killer);
    if(killer != null)
    {
      L2Player pk = killer.getPlayer();
      L2Player player = getPlayer();
      if(pk != null && player != null)
      {
        L2Party party = pk.getParty();
        if(party == null)
        {
          GCSArray<QuestState> killList = pk.getNotifyOfPlayerKillList();
          if(killList != null)
          {
            for(QuestState qs : killList)
            {
              qs.getQuest().notifyPlayerKill(player, qs);
            }
          }
        }
        else
        {
          for(L2Player member : party.getPartyMembers())
          {
            if(member != null && member.isInRange(pk, 2000))
            {
              GCSArray<QuestState> killList = member.getNotifyOfPlayerKillList();
              if(killList != null)
              {
                for(QuestState qs : killList)
                {
                  qs.getQuest().notifyPlayerKill(player, qs);
                }
              }
            }
          }
        }
      }
    }
    if(_NotifyQuestOfDeathList != null)
    {
      for(QuestState qs : _NotifyQuestOfDeathList)
      {
        qs.getQuest().notifyDeath(killer, this, qs);
      }
      _NotifyQuestOfDeathList = null;
    }
  }

  @Override
  public int getPAtkSpd()
  {
    return Math.max((int) (calcStat(Stats.POWER_ATTACK_SPEED, calcStat(Stats.ATK_BASE, _template.basePAtkSpd, null, null), null, null)), 1);
  }

  @Override
  public int getPAtk(final L2Character target)
  {
    double init = getActiveWeaponInstance() == null ? _template.basePAtk : 0;
    return (int) calcStat(Stats.POWER_ATTACK, init, target, null);
  }

  @Override
  public int getMAtk(final L2Character target, final L2Skill skill)
  {
    if(skill != null && skill.getMatak() > 0)
    {
      return skill.getMatak();
    }
    final double init = getActiveWeaponInstance() == null ? _template.baseMAtk : 0;
    return (int) calcStat(Stats.MAGIC_ATTACK, init, target, skill);
  }

  @Override
  public boolean isAttackable(L2Character attacker)
  {
    return checkTarget(attacker, true);
  }

  @Override
  public boolean isAutoAttackable(L2Character attacker)
  {
    return checkTarget(attacker, false);
  }

  private boolean checkTarget(L2Character attacker, boolean force)
  {
    L2Player player = getPlayer();
    if(attacker == null || player == null || attacker == this || (attacker == player && !isSummon()) || isDead() || attacker.isAlikeDead())
    {
      return false;
    }
    if(!GeoEngine.canSeeTarget(attacker, this, false) || getReflection() != attacker.getReflection() || isInvisible())
    {
      return false;
    }
    if(isInVehicle())
    {
      return false;
    }
    L2Player pcAttacker = attacker.getPlayer();
    L2Clan clan1 = player.getClan();
    if(pcAttacker != null)
    {
      if(pcAttacker.isInVehicle())
      {
        return false;
      }
      // Только враг и только если он еше не проиграл.
      Duel duel1 = player.getDuel();
      Duel duel2 = pcAttacker.getDuel();
      if(player != pcAttacker && duel1 != null && duel1 == duel2)
      {
        if(duel1.getTeamForPlayer(pcAttacker) == duel1.getTeamForPlayer(player))
        {
          return false;
        }
        if(duel1.getDuelState(player.getStoredId()) != Duel.DuelState.Fighting)
        {
          return false;
        }
        if(duel1.getDuelState(pcAttacker.getStoredId()) != Duel.DuelState.Fighting)
        {
          return false;
        }
        return true;
      }
      if(!force && duel1 != null && duel1 != duel2)
      {
        return false;
      }
      if(player.isInZone(ZoneType.epic) != pcAttacker.isInZone(ZoneType.epic))
      {
        return false;
      }
      if((player.isInOlympiadMode() || pcAttacker.isInOlympiadMode()) && player.getOlympiadGameId() != pcAttacker.getOlympiadGameId()) // На всякий случай
      {
        return false;
      }
      if(player.isInOlympiadMode() && !player.isOlympiadCompStart()) // Бой еще не начался
      {
        return false;
      }
      if(player.isInOlympiadMode() && player.isOlympiadCompStart() && player.getOlympiadSide() == pcAttacker.getOlympiadSide()) // Свою команду атаковать нельзя
      {
        return false;
      }
      if(pcAttacker.getTeam() > 0 && pcAttacker.isChecksForTeam() && player.getTeam() == 0) // Запрет на атаку/баф участником эвента незарегистрированного игрока
      {
        return false;
      }
      if(player.getTeam() > 0 && player.isChecksForTeam() && pcAttacker.getTeam() == 0) // Запрет на атаку/баф участника эвента незарегистрированным игроком
      {
        return false;
      }
      if(player.getTeam() > 0 && player.isChecksForTeam() && pcAttacker.getTeam() > 0 && pcAttacker.isChecksForTeam() && player.getTeam() == pcAttacker.getTeam()) // Свою команду атаковать нельзя
      {
        return false;
      }
      if(isInZoneBattle() != attacker.isInZoneBattle() && !player.getPlayerAccess().PeaceAttack)
      {
        return false;
      }
      if((isInZonePeace() || pcAttacker.isInZonePeace()) && !player.getPlayerAccess().PeaceAttack)
      {
        return false;
      }
      if(!force && player.getParty() != null && player.getParty() == pcAttacker.getParty())
      {
        return false;
      }
      if(isInZoneBattle())
      {
        return true;
      } // Остальные условия на аренах и на олимпиаде проверять не требуется
      if(!force && player.getClanId() != 0 && player.getClanId() == pcAttacker.getClanId())
      {
        return false;
      }
      if(isInZone(ZoneType.Siege) && attacker.isInZone(ZoneType.Siege))
      {
        if(player.getTerritorySiege() > -1 && player.getTerritorySiege() == pcAttacker.getTerritorySiege())
        {
          return false;
        }
        L2Clan clan2 = pcAttacker.getClan();
        if(clan1 == null || clan2 == null)
        {
          return true;
        }
        if(clan1.getSiege() == null || clan2.getSiege() == null)
        {
          return true;
        }
        if(clan1.getSiege() != clan2.getSiege())
        {
          return true;
        }
        if(clan1.isDefender() && clan2.isDefender())
        {
          return false;
        }
        if(clan1.getSiege().isMidVictory())
        {
          return true;
        }
        if(clan1.isAttacker() && clan2.isAttacker())
        {
          return false;
        }
        return true;
      }
      if(pcAttacker.atMutualWarWith(player))
      {
        return true;
      }
      // Защита от развода на флаг с копьем
      if(!force && pcAttacker.getPvpFlag() == 0 && getPvpFlag() != 0 && pcAttacker.getAI() != null && pcAttacker.getAI().getAttackTarget() != this)
      {
        return false;
      }
      if(player.getKarma() > 0 || player.getPvpFlag() != 0)
      {
        return true;
      }
      return force;
    }
    if(attacker.isSiegeGuard() && clan1 != null && clan1.isDefender() && SiegeManager.getSiege(this, true) == clan1.getSiege())
    {
      return false;
    }
    if(!force && isInZonePeace()) // Гварды с пикой, будут атаковать только одиночные цели в городе
    {
      return false;
    }
    return true;
  }

  @Override
  public int getKarma()
  {
    L2Player player = getPlayer();
    return player == null ? 0 : player.getKarma();
  }

  @Override
  public void callSkill(L2Skill skill, GArray<L2Character> targets, boolean useActionSkills)
  {
    L2Player player = getPlayer();
    if(player == null)
    {
      return;
    }
    GArray<L2Character> toRemove = new GArray<L2Character>();
    if(useActionSkills && !skill.altUse() && !skill.getSkillType().equals(SkillType.BEAST_FEED))
    {
      for(L2Character target : targets)
      {
        if(target.isInvul() && skill.isOffensive() && (skill.getSkillType() != SkillType.STEAL_BUFF || (target.isPlayer() && ((L2Player) target).isGM())) && !target.isArtefact())
        {
          toRemove.add(target);
        }
        if(!skill.isOffensive())
        {
          if(target.isPlayable() && target != getPet() && !(this instanceof L2Summon && target == player))
          {
            int aggro = skill.getEffectPoint() != 0 ? skill.getEffectPoint() : Math.max(1, (int) skill.getPower());
            for(Entry<L2NpcInstance, HateInfo> entry : target.getHateList().entrySet())
            {
              if(entry.getKey() != null && !entry.getKey().isDead() && entry.getValue().hate > 0 && entry.getKey().isInRange(this, 2000) && entry.getKey().getAI().getIntention() == CtrlIntention.AI_INTENTION_ATTACK)
              {
                if(!skill.isHandler() && entry.getKey().paralizeOnAttack(player))
                {
                  if(Config.PARALIZE_ON_RAID_DIFF)
                  {
                    paralizeMe(entry.getKey());
                  }
                  return;
                }
                entry.getKey().getAI().notifyEvent(CtrlEvent.EVT_SEE_SPELL, skill, this);
                if(GeoEngine.canSeeTarget(entry.getKey(), target, false)) // Моб агрится только если видит цель, которую лечишь/бафаешь.
                {
                  entry.getKey().getAI().notifyEvent(CtrlEvent.EVT_AGGRESSION, this, aggro);
                }
              }
            }
          }
        }
        else if(target.isNpc())
        {
          // mobs will hate on debuff
          if(target.paralizeOnAttack(player))
          {
            if(Config.PARALIZE_ON_RAID_DIFF)
            {
              paralizeMe(target);
            }
            return;
          }
          target.getAI().notifyEvent(CtrlEvent.EVT_SEE_SPELL, skill, this);
          if(!skill.isAI())
          {
            int damage = skill.getEffectPoint() != 0 ? skill.getEffectPoint() : 1;
            target.getAI().notifyEvent(CtrlEvent.EVT_ATTACKED, this, damage);
            target.getAI().notifyEvent(CtrlEvent.EVT_AGGRESSION, this, damage);
          }
        }
        // Check for PvP Flagging / Drawing Aggro
        if(checkPvP(target, skill))
        {
          startPvPFlag(target);
        }
      }
    }
    for(L2Character cha : toRemove)
    {
      targets.remove(cha);
    }
    super.callSkill(skill, targets, useActionSkills);
  }

  @Override
  public void setXYZ(int x, int y, int z, boolean MoveTask)
  {
    super.setXYZ(x, y, z, MoveTask);
    L2Player player = getPlayer();
    if(!MoveTask || player == null || isAlikeDead() || isInvul() || !isVisible() || getCurrentRegion() == null)
    {
      return;
    }
    long now = System.currentTimeMillis();
    if(now - _checkAggroTimestamp < Config.AGGRO_CHECK_INTERVAL || player.getNonAggroTime() > now)
    {
      return;
    }
    _checkAggroTimestamp = now;
    if(getAI().getIntention() == CtrlIntention.AI_INTENTION_FOLLOW && (!isPlayer() || getFollowTarget() != null && getFollowTarget().getPlayer() != null && !getFollowTarget().getPlayer().isSilentMoving()))
    {
      return;
    }
    for(L2NpcInstance obj : L2World.getAroundNpc(this))
    {
      if(obj != null)
      {
        obj.getAI().checkAggression(this);
      }
    }
  }

  /**
   * Оповещает других игроков о поднятии вещи
   *
   * @param item предмет который был поднят
   */
  public void broadcastPickUpMsg(L2ItemInstance item)
  {
    L2Player player = getPlayer();
    if(item == null || player == null || player.isInvisible())
    {
      return;
    }
    if(item.isEquipable() && !(item.getItem() instanceof L2EtcItem))
    {
      SystemMessage msg;
      String player_name = player.getName();
      if(item.getEnchantLevel() > 0)
      {
        int msg_id = isPlayer() ? SystemMessage.ATTENTION_S1_PICKED_UP__S2_S3 : SystemMessage.ATTENTION_S1_PET_PICKED_UP__S2_S3;
        msg = new SystemMessage(msg_id).addString(player_name).addNumber(item.getEnchantLevel()).addItemName(item.getItemId());
      }
      else
      {
        int msg_id = isPlayer() ? SystemMessage.ATTENTION_S1_PICKED_UP_S2 : SystemMessage.ATTENTION_S1_PET_PICKED_UP__S2_S3;
        msg = new SystemMessage(msg_id).addString(player_name).addItemName(item.getItemId());
      }
      player.broadcastPacket(msg);
    }
  }

  public void paralizeMe(L2Character effector)
  {
    L2Skill revengeSkill = SkillTable.getInstance().getInfo(L2Skill.SKILL_RAID_CURSE, 1);
    L2Player player = getPlayer();
    if(player != this)
    {
      revengeSkill.getEffects(effector, this, false, false);
    }
    if(player != null)
    {
      revengeSkill.getEffects(effector, player, false, false);
    }
  }

  /**
   * Set the Silent Moving mode Flag.<BR><BR>
   */
  public void setSilentMoving(final boolean flag)
  {
    if(flag)
    {
      _isSilentMoving++;
    }
    else
    {
      _isSilentMoving--;
    }
  }

  /**
   * @return True if the Silent Moving mode is active.<BR><BR>
   */
  public boolean isSilentMoving()
  {
    return _isSilentMoving > 0;
  }
}
TOP

Related Classes of l2p.gameserver.model.L2Playable

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.