Package l2p.gameserver.model

Source Code of l2p.gameserver.model.L2Zone$DamageTask

package l2p.gameserver.model;

import java.util.HashMap;
import java.util.logging.Logger;

import l2p.common.ThreadPoolManager;
import l2p.extensions.listeners.MethodCollection;
import l2p.extensions.listeners.engine.DefaultListenerEngine;
import l2p.extensions.listeners.engine.ListenerEngine;
import l2p.extensions.listeners.events.L2Zone.L2ZoneEnterLeaveEvent;
import l2p.extensions.scripts.Functions;
import l2p.gameserver.serverpackets.SystemMessage;
import l2p.gameserver.skills.Stats;
import l2p.gameserver.skills.funcs.FuncAdd;
import l2p.gameserver.tables.SkillTable;
import l2p.util.GArray;
import l2p.util.Location;
import l2p.util.Rnd;
import l2p.util.Util;

public class L2Zone
{
  private static Logger _log = Logger.getLogger(L2Zone.class.getName());

  public static enum ZoneType
  {
    Town,
    Castle,
    ClanHall,
    Fortress,
    OlympiadStadia,
    MonsterDerbyTrack,
    CastleDefenderSpawn,
    Fishing,
    Underground,
    Siege,
    water,
    battle_zone,
    damage,
    instant_skill,
    mother_tree,
    peace_zone,
    poison,
    ssq_zone,
    swamp,
    no_escape,
    no_landing,
    no_restart,
    no_spawn,
    siege_residense,
    // территория замка, ограничена забором
    dummy,
    offshore,
    unblock_actions,
    no_water,
    epic,
    monster_trap,
    no_summon,
    UnderGroundColiseum;
  }

  int _id;
  ZoneType _type;
  private String _name;
  private L2Territory _loc;
  private L2Territory _restartPoints;
  private L2Territory _PKrestartPoints;
  private int _entering_message_no;
  private int _leaving_message_no;
  private boolean _active;
  L2Skill _skill;
  int _skillProb;
  long _unitTick;
  private long _initialDelay;
  private ZoneTarget _target;
  private int _index;
  private int _taxById;
  private long _restartTime;
  private String _blockedActions;
  public static final String BLOCKED_ACTION_PRIVATE_STORE = "private store";
  public static final String BLOCKED_ACTION_PRIVATE_WORKSHOP = "private workshop";
  private String _event;
  private int _reflectionId;
  private ListenerEngine<L2Zone> listenerEngine;
  private DamageTask damageTask;
  private final GArray<L2Object> _objects = new GArray<L2Object>(0);
  private final HashMap<L2Character, ZoneSkillTimer> _skillTimers = new HashMap<L2Character, ZoneSkillTimer>(0);
  /**
   * Ордер в зонах, с ним мы и добавляем/убираем статы.
   * TODO: сравнить ордер с оффом, пока от фонаря
   */
  public final static int ZONE_STATS_ORDER = 0x40;
  /**
   * Сообщение которое шлется при уроне от зоны (не скилла)
   * К примеру на осадах. Пока это только 686 (You have received $s1 damage from the fire of magic.)
   */
  private int messageNumber;
  /**
   * Урон от зоны по хп
   */
  private int damageOnHP;
  /**
   * Урон от зоны по мп
   */
  private int damageOnMP;
  /**
   * Бонус/штраф к скорости движения
   */
  private int moveBonus;
  /**
   * Бонус регенерации хп
   */
  private int regenBonusHP;
  /**
   * Бонус регенерации мп
   */
  private int regenBonusMP;
  /**
   * Раса на которую применим эффект
   */
  private String affectRace;

  public L2Zone(int id)
  {
    _id = id;
  }

  public final int getId()
  {
    return _id;
  }

  @Override
  public final String toString()
  {
    return "zone '" + _id + "'";
  }

  public ZoneType getType()
  {
    return _type;
  }

  public void setType(ZoneType type)
  {
    _type = type;
  }

  public void setLoc(L2Territory t)
  {
    _loc = t;
  }

  public void setRestartPoints(L2Territory t)
  {
    _restartPoints = t;
  }

  public void setPKRestartPoints(L2Territory t)
  {
    _PKrestartPoints = t;
  }

  public L2Territory getLoc()
  {
    return _loc;
  }

  public L2Territory getRestartPoints()
  {
    return _restartPoints;
  }

  public L2Territory getPKRestartPoints()
  {
    return _PKrestartPoints;
  }

  public Location getSpawn()
  {
    // При ошибке портанет во флоран
    if(_restartPoints == null)
    {
      _log.warning("L2Zone.getSpawn(): restartPoint not found for " + toString());
      return new Location(17817, 170079, -3530);
    }
    GArray<int[]> coords = _restartPoints.getCoords();
    int[] coord = coords.get(Rnd.get(coords.size()));
    return new Location(coord);
  }

  public GArray<int[]> getSpawns()
  {
    return _restartPoints.getCoords();
  }

  public Location getPKSpawn()
  {
    if(_PKrestartPoints == null)
    {
      return getSpawn();
    }
    GArray<int[]> coords = _PKrestartPoints.getCoords();
    int rnd = Rnd.get(coords.size());
    int[] coord = coords.get(rnd);
    return new Location(coord);
  }

  /**
   * Проверяет находятся ли даные координаты в зоне.
   * _loc - стандартная территория для зоны
   *
   * @param x координата
   * @param y координата
   * @return находятся ли координаты в локации
   */
  public boolean checkIfInZone(int x, int y)
  {
    return _loc != null && _loc.isInside(x, y);
  }

  public boolean checkIfInZone(int x, int y, int z)
  {
    return _loc != null && _loc.isInside(x, y, z);
  }

  public boolean checkIfInZone(L2Object obj)
  {
    return _loc != null && _loc.isInside(obj.getX(), obj.getY(), obj.getZ());
  }

  public final double findDistanceToZone(L2Object obj, boolean includeZAxis)
  {
    return findDistanceToZone(obj.getX(), obj.getY(), obj.getZ(), includeZAxis);
  }

  public final double findDistanceToZone(int x, int y, int z, boolean includeZAxis)
  {
    double closestDistance = 99999999;
    if(_loc == null)
    {
      return closestDistance;
    }
    double distance;
    for(int[] coord : _loc.getCoords())
    {
      distance = Util.calculateDistance(x, y, z, coord[0], coord[1], (coord[2] + coord[3]) / 2, includeZAxis);
      if(distance < closestDistance)
      {
        closestDistance = distance;
      }
    }
    return closestDistance;
  }

  public GArray<int[]> getCoords()
  {
    return _loc.getCoords();
  }

  /**
   * Обработка входа в территорию
   * Ojbect всегда добавляется в список вне зависимости от активности территории.
   * Если зона акивная, то обработается вход в зону
   *
   * @param object кто входит
   */
  public void doEnter(L2Object object)
  {
    synchronized(_objects)
    {
      if(!_objects.contains(object))
      {
        _objects.add(object);
      }
      else
      {
        _log.severe("Attempt of double object add to zone " + _name + " id " + _id);
      }
    }
    if(!isActive())
    {
      return;
    }
    onZoneEnter(object);
  }

  /**
   * Обработка выхода из зоны
   * Object всегда убирается со списка вне зависимости от зоны
   * Если зона активная, то обработается выход из зоны
   *
   * @param object кто выходит
   */
  public void doLeave(L2Object object, boolean notify)
  {
    synchronized(_objects)
    {
      boolean remove = _objects.remove(object);
      if(!remove)
      {
        _log.severe("Attempt remove object from zone " + _name + " id " + _id + " where it's absent");
      }
    }
    if(!isActive())
    {
      return;
    }
    if(notify)
    {
      onZoneLeave(object);
    }
  }

  /**
   * Обработка входа в зону
   *
   * @param object кто входит
   */
  private void onZoneEnter(L2Object object)
  {
    if(object.inObserverMode())
    {
      return;
    }
    object.addZone(this);
    getListenerEngine().fireMethodInvoked(new L2ZoneEnterLeaveEvent(MethodCollection.L2ZoneObjectEnter, this, new L2Object[] {object}));
    checkEffects(object, true);
    addZoneStats((L2Character) object);
    if(object.isPlayer())
    {
      ((L2Player) object).doZoneCheck(_entering_message_no);
    }
  }

  /**
   * Обработка выхода из зоны
   *
   * @param object кто выходит
   */
  private void onZoneLeave(L2Object object)
  {
    if(object.inObserverMode())
    {
      return;
    }
    object.removeZone(this);
    getListenerEngine().fireMethodInvoked(new L2ZoneEnterLeaveEvent(MethodCollection.L2ZoneObjectLeave, this, new L2Object[] {object}));
    checkEffects(object, false);
    removeZoneStats((L2Character) object);
    if(object.isPlayer())
    {
      ((L2Player) object).doZoneCheck(_leaving_message_no);
    }
  }

  /**
   * Добавляет статы зоне
   *
   * @param object обьект которому добавляется
   */
  private void addZoneStats(L2Character object)
  {
    // Проверка цели
    if(_target != null)
    {
      if(!checkTarget(object))
      {
        return;
      }
    }
    // Скорость движения накладывается только на L2Playable
    // affectRace в базе не указан, если надо будет влияние, то поправим
    if(getMoveBonus() != 0)
    {
      if(object.isPlayable())
      {
        object.addStatFunc(new FuncAdd(Stats.RUN_SPEED, ZONE_STATS_ORDER, this, getMoveBonus()));
        object.sendChanges();
      }
    }
    // Если раса указана, то это уже не NPC
    if(affectRace != null && !object.isPlayer())
    {
      return;
    }
    // Если у нас раса не "all"
    if(affectRace != null && !affectRace.equalsIgnoreCase("all"))
    {
      L2Player player = object.getPlayer();
      // если раса не подходит
      if(!player.getRace().toString().equalsIgnoreCase(affectRace))
      {
        return;
      }
    }
    // Если у нас есть что регенить
    if(getRegenBonusHP() != 0)
    {
      object.addStatFunc(new FuncAdd(Stats.REGENERATE_HP_RATE, ZONE_STATS_ORDER, this, getRegenBonusHP()));
    }
    // Если у нас есть что регенить
    if(getRegenBonusMP() != 0)
    {
      object.addStatFunc(new FuncAdd(Stats.REGENERATE_MP_RATE, ZONE_STATS_ORDER, this, getRegenBonusMP()));
    }
  }

  /**
   * Убирает добавленые зоной статы
   *
   * @param object обьект у которого убирается
   */
  private void removeZoneStats(L2Character object)
  {
    if(getRegenBonusHP() == 0 && getRegenBonusMP() == 0 && getMoveBonus() == 0)
    {
      return;
    }
    object.removeStatsOwner(this);
    if(getMoveBonus() > 0)
    {
      object.sendChanges();
    }
  }

  /**
   * Применяет эффекты при входе/выходе из(в) зону
   *
   * @param object обьект
   * @param enter  вошел или вышел
   */
  private void checkEffects(L2Object object, boolean enter)
  {
    if(_event != null && _event.startsWith("script"))
    {
      String[] param = _event.split(";");
      Functions.callScripts(param[1], param[2], new Object[] {this, object, enter});
    }
    if(_skill == null || _target == null)
    {
      return;
    }
    // Проверяет тип цели.
    // affectRace ну указан.
    if(!checkTarget(object))
    {
      return;
    }
    L2Character p = (L2Character) object;
    ZoneSkillTimer rem = _skillTimers.remove(p);
    if(rem != null)
    {
      rem.setCanceled(true);
    }
    if(enter)
    {
      ZoneSkillTimer t = new ZoneSkillTimer(p, _skill, _skillProb, _unitTick);
      _skillTimers.put(p, t);
      if(_initialDelay > 0)
      {
        ThreadPoolManager.getInstance().scheduleGeneral(t, _initialDelay);
      }
      else
      {
        t.run();
      }
    }
  }

  /**
   * Проверяет подходит ли обьект для вызвавшего действия
   *
   * @param object обьект
   * @return подошел ли
   */
  private boolean checkTarget(L2Object object)
  {
    switch(_target)
    {
      case pc:
        return object.isPlayable();
      case only_pc:
        return object.isPlayer();
      case npc:
        return object.isNpc();
    }
    return false;
  }

  public L2Object[] getObjects()
  {
    synchronized(_objects)
    {
      return _objects.toArray(new L2Object[_objects.size()]);
    }
  }

  public GArray<L2Object> getInsideObjectsIncludeZ()
  {
    L2Object[] all_objects = getObjects();
    GArray<L2Object> result = new GArray<L2Object>();
    for(L2Object obj : all_objects)
    {
      if(obj != null && _loc.isInside(obj))
      {
        result.add(obj);
      }
    }
    return result;
  }

  public GArray<L2Player> getInsidePlayers()
  {
    L2Object[] all_objects = getObjects();
    GArray<L2Player> result = new GArray<L2Player>();
    for(L2Object obj : all_objects)
    {
      if(obj != null && obj.isPlayer())
      {
        result.add((L2Player) obj);
      }
    }
    return result;
  }

  public GArray<L2Player> getInsidePlayersIncludeZ()
  {
    L2Object[] all_objects = getObjects();
    GArray<L2Player> result = new GArray<L2Player>();
    for(L2Object obj : all_objects)
    {
      if(obj != null && obj.isPlayer() && _loc.isInside(obj))
      {
        result.add((L2Player) obj);
      }
    }
    return result;
  }

  /**
   * Установка активности зоны
   *
   * @param value активна ли зона
   */
  public void setActive(boolean value)
  {
    if(_active == value)
    {
      return;
    }
    synchronized(_objects)
    {
      _active = value;
      for(L2Object obj : _objects)
      {
        if(_active)
        {
          onZoneEnter(obj);
        }
        else
        {
          onZoneLeave(obj);
        }
      }
    }
    setDamageTaskActive(value);
  }

  /**
   * Запускает или останавливает таск урона в зоне.<br>
   * <b>Таск <font color="red">не</font> запустится если урон по хп и мп равны 0</b>
   *
   * @param value запустить или остановить таск урона
   */
  public void setDamageTaskActive(boolean value)
  {
    if(value && (getDamageOnHP() > 0 || getDamageOnMP() > 0))
    {
      new DamageTask().start();
    }
    else
    {
      damageTask = null;
    }
  }

  public boolean isActive()
  {
    return _active;
  }

  public final String getName()
  {
    return _name;
  }

  public final void setName(String name)
  {
    _name = name;
  }

  public final int getEnteringMessageId()
  {
    return _entering_message_no;
  }

  public final void setEnteringMessageId(int id)
  {
    _entering_message_no = id;
  }

  public final int getLeavingMessageId()
  {
    return _leaving_message_no;
  }

  public final void setLeavingMessageId(int id)
  {
    _leaving_message_no = id;
  }

  public final void setIndex(int index)
  {
    _index = index;
  }

  public final int getIndex()
  {
    return _index;
  }

  public final void setTaxById(int id)
  {
    _taxById = id;
  }

  public final Integer getTaxById()
  {
    return _taxById;
  }

  public void setSkill(String skill)
  {
    if(skill == null || skill.equalsIgnoreCase("null"))
    {
      return;
    }
    String[] sk = skill.split(";");
    setSkill(SkillTable.getInstance().getInfo(Short.parseShort(sk[0]), Short.parseShort(sk[1])));
  }

  public void setSkill(L2Skill skill)
  {
    _skill = skill;
  }

  public void setSkillProb(String chance)
  {
    if(chance == null)
    {
      _skillProb = -1;
      return;
    }
    _skillProb = Integer.parseInt(chance);
  }

  public void setUnitTick(String delay)
  {
    if(delay == null)
    {
      _unitTick = 1000;
      return;
    }
    _unitTick = Integer.parseInt(delay) * 1000L;
  }

  public void setInitialDelay(String delay)
  {
    if(delay == null)
    {
      _initialDelay = 0;
      return;
    }
    _initialDelay = Integer.parseInt(delay) * 1000L;
  }

  private static class ZoneSkillTimer implements Runnable
  {
    private boolean canceled = false;
    private L2Character _target;
    private L2Skill _skill;
    private int _skillProb;
    private long _unitTick;

    public ZoneSkillTimer(L2Character target, L2Skill skill, int skillProb, long unitTick)
    {
      _target = target;
      _skill = skill;
      _skillProb = skillProb;
      _unitTick = unitTick;
    }

    public void run()
    {
      if(canceled)
      {
        return;
      }
      if(Rnd.chance(_skillProb) && !_target.isDead())
      {
        _skill.getEffects(_target, _target, false, false);
      }
      ThreadPoolManager.getInstance().scheduleGeneral(this, _unitTick);
    }

    public void setCanceled(boolean val)
    {
      canceled = val;
    }
  }

  public void setTarget(String target)
  {
    if(target == null)
    {
      return;
    }
    _target = ZoneTarget.valueOf(target);
  }

  public enum ZoneTarget
  {
    pc,
    npc,
    only_pc
  }

  public long getRestartTime()
  {
    return _restartTime;
  }

  public L2Skill getZoneSkill()
  {
    return _skill;
  }

  public ZoneTarget getZoneTarget()
  {
    return _target;
  }

  public void setRestartTime(long restartTime)
  {
    _restartTime = restartTime;
  }

  public void setBlockedActions(String blockedActions)
  {
    _blockedActions = blockedActions;
  }

  public boolean isActionBlocked(String action)
  {
    return _blockedActions != null && _blockedActions.contains(action);
  }

  public ListenerEngine<L2Zone> getListenerEngine()
  {
    if(listenerEngine == null)
    {
      listenerEngine = new DefaultListenerEngine<L2Zone>(this);
    }
    return listenerEngine;
  }

  /**
   * Номер системного вообщения которое будет отослано игроку при нанесении урона зоной
   *
   * @return SystemMessage ID
   */
  public int getMessageNumber()
  {
    return messageNumber;
  }

  /**
   * Устанавлевает номер системного сообщение которое будет отослано игроку при уроне зоной
   *
   * @param messageNumber SystemMessage ID
   */
  public void setMessageNumber(int messageNumber)
  {
    this.messageNumber = messageNumber;
  }

  /**
   * Устанавлевает номер системного сообщение которое будет отослано игроку при уроне зоной
   *
   * @param number SystemMessage ID - Системное сообщение сторой
   */
  public void setMessageNumber(String number)
  {
    setMessageNumber(number == null ? 0 : Integer.parseInt(number));
  }

  /**
   * Сколько урона зона нанесет по хп
   *
   * @return количество урона
   */
  public int getDamageOnHP()
  {
    return damageOnHP;
  }

  /**
   * Установка урона по хп зоной
   *
   * @param damageOnHP сколько зона нанесет урона по хп
   */
  public void setDamageOnHP(int damageOnHP)
  {
    this.damageOnHP = damageOnHP;
  }

  /**
   * Установка урона по хп зоной. Парсит строку.
   *
   * @param damage урон в строке
   */
  public void setDamageOnHP(String damage)
  {
    setDamageOnHP(damage == null ? 0 : Integer.parseInt(damage));
  }

  /**
   * Сколько урона зона нанесет по мп
   *
   * @return количество урона
   */
  public int getDamageOnMP()
  {
    return damageOnMP;
  }

  /**
   * Установка урона по мп зоной
   *
   * @param damageOnMP сколько зона нанесет урона по мп
   */
  public void setDamageOnMP(int damageOnMP)
  {
    this.damageOnMP = damageOnMP;
  }

  /**
   * Установка урона по мп зоной. Парсит строку.
   *
   * @param damage урон в строке
   */
  public void setDamageOnМP(String damage)
  {
    setDamageOnMP(damage == null ? 0 : Integer.parseInt(damage));
  }

  /**
   * @return Бонус к скорости движения в зоне
   */
  public int getMoveBonus()
  {
    return moveBonus;
  }

  /**
   * Устанавливает бонус на движение в зоне
   *
   * @param moveBonus бонус
   */
  public void setMoveBonus(int moveBonus)
  {
    this.moveBonus = moveBonus;
  }

  /**
   * Устанавливает бонус на движение в зоне
   *
   * @param moveBonus бонус
   */
  public void setMoveBonus(String moveBonus)
  {
    setMoveBonus(moveBonus == null ? 0 : Integer.parseInt(moveBonus));
  }

  /**
   * Возвращает бонус регенерации хп в этой зоне
   *
   * @return Бонус регенарации хп в этой зоне
   */
  public int getRegenBonusHP()
  {
    return regenBonusHP;
  }

  /**
   * Устанавливает бонус регена хп в этой зоне. Парсит строку
   *
   * @param bonus бонус регена
   */
  public void setRegenBonusHP(String bonus)
  {
    setRegenBonusHP(bonus == null ? 0 : Integer.parseInt(bonus));
  }

  /**
   * Устанавливает бонус регенерации хп в этой зоне
   *
   * @param regenBonusHP бонус регена ХП
   */
  public void setRegenBonusHP(int regenBonusHP)
  {
    this.regenBonusHP = regenBonusHP;
  }

  /**
   * Возвращает бонус регенерации мп в этой зоне
   *
   * @return Бонус регенарации мп в этой зоне
   */
  public int getRegenBonusMP()
  {
    return regenBonusMP;
  }

  /**
   * Устанавливает бонус регенерации хп в этой зоне
   *
   * @param regenBonusMP бонус регена МП
   */
  public void setRegenBonusMP(int regenBonusMP)
  {
    this.regenBonusMP = regenBonusMP;
  }

  /**
   * Устанавливает бонус регена мп в этой зоне. Парсит строку
   *
   * @param bonus бонус регена
   */
  public void setRegenBonusMP(String bonus)
  {
    setRegenBonusMP(bonus == null ? 0 : Integer.parseInt(bonus));
  }

  /**
   * Возвращает расу на которую примени эффект. Раса может быть:
   * <br><b>all</b> - любая раса
   * <br><b>null</b> - проверка не применяется
   * ну или любая из энумы Race
   *
   * @return раса
   * @see l2p.gameserver.model.base.Race
   */
  public String getAffectRace()
  {
    return affectRace;
  }

  /**
   * Устанавливает расу зоне на которую будут применятся эффекты. Раса может быть:
   * <br><b>all</b> - любая раса
   * <br><b>null</b> - проверка не применяется
   * ну или любая из энумы Race
   *
   * @param affectRace строка с расой
   * @see l2p.gameserver.model.base.Race
   */
  public void setAffectRace(String affectRace)
  {
    if(affectRace != null)
    {
      affectRace = affectRace.toLowerCase().replace(" ", "");
    }
    this.affectRace = affectRace;
  }

  /**
   * Класс используется для нанесения урона всем кто в зоне.
   */
  private class DamageTask implements Runnable
  {
    public void run()
    {
      if(damageTask != this || !isActive())
      {
        return;
      }
      synchronized(_objects)
      {
        for(L2Object object : _objects)
        {
          if(_target != null && !checkTarget(object)) // Если явно указана цель
          {
            continue;
          }
          if(_target == null && !object.isPlayable()) // Если цель не указана, то валим только игроков
          {
            continue;
          }
          L2Character target = (L2Character) object;
          int hp = getDamageOnHP();
          int mp = getDamageOnMP();
          int message = getMessageNumber();
          if(hp > 0)
          {
            target.reduceCurrentHp(hp, null, null, true, true, true, false);
            if(message > 0)
            {
              target.sendPacket(new SystemMessage(message).addNumber(hp));
            }
          }
          if(mp > 0)
          {
            target.reduceCurrentMp(mp, null);
            if(message > 0)
            {
              target.sendPacket(new SystemMessage(message).addNumber(mp));
            }
          }
        }
      }
      ThreadPoolManager.getInstance().scheduleGeneral(this, 1000);
    }

    /**
     * Запускает таймер нанесения урона зоной
     */
    public void start()
    {
      damageTask = this;
      if(_initialDelay == 0)
      {
        run();
        return;
      }
      ThreadPoolManager.getInstance().scheduleGeneral(this, _initialDelay);
    }
  }

  public String getEvent()
  {
    return _event;
  }

  public void setEvent(String event)
  {
    _event = event;
  }

  public void setReflectionId(int val)
  {
    _reflectionId = val;
  }

  public int getReflectionId()
  {
    return _reflectionId;
  }

  public void setParam(String name, String value)
  {
    // TODO: implement
  }
}
TOP

Related Classes of l2p.gameserver.model.L2Zone$DamageTask

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.