Package l2p.gameserver.model.instances

Source Code of l2p.gameserver.model.instances.L2RaidBossInstance$DamagerInfo

package l2p.gameserver.model.instances;

import javolution.util.FastMap;
import l2p.Config;
import l2p.common.ThreadPoolManager;
import l2p.gameserver.cache.Msg;
import l2p.gameserver.idfactory.IdFactory;
import l2p.gameserver.instancemanager.QuestManager;
import l2p.gameserver.instancemanager.RaidBossSpawnManager;
import l2p.gameserver.instancemanager.RaidBossSpawnManager.Status;
import l2p.gameserver.model.L2Character;
import l2p.gameserver.model.L2CommandChannel;
import l2p.gameserver.model.L2Party;
import l2p.gameserver.model.L2Player;
import l2p.gameserver.model.L2Skill;
import l2p.gameserver.model.base.Experience;
import l2p.gameserver.model.quest.Quest;
import l2p.gameserver.model.quest.QuestState;
import l2p.gameserver.serverpackets.SystemMessage;
import l2p.gameserver.tables.NpcTable;
import l2p.gameserver.tables.SkillTable;
import l2p.gameserver.templates.L2NpcTemplate;
import l2p.util.GArray;
import l2p.util.Log;
import l2p.util.MinionList;
import l2p.util.PrintfFormat;
import l2p.util.Util;

import java.util.HashMap;
import java.util.HashSet;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;

public class L2RaidBossInstance extends L2MonsterInstance
{
  protected static final Logger _log = Logger.getLogger(L2RaidBossInstance.class.getName());
  private ScheduledFuture<?> minionMaintainTask;
  private static final int RAIDBOSS_MAINTENANCE_INTERVAL = 60000;
  private static final int MINION_UNSPAWN_INTERVAL = 5000; //time to unspawn minions when boss is dead, msec
  private RaidBossSpawnManager.Status _raidStatus;

  public L2RaidBossInstance(int objectId, L2NpcTemplate template)
  {
    super(objectId, template);
  }

  @Override
  protected int getMaintenanceInterval()
  {
    return RAIDBOSS_MAINTENANCE_INTERVAL;
  }

  protected int getMinionUnspawnInterval()
  {
    return MINION_UNSPAWN_INTERVAL;
  }

  protected int getKilledInterval(L2MinionInstance minion)
  {
    return Config.MinionRespawnTime * 60000; //2 minutes to respawn
  }

  @Override
  public void notifyMinionDied(L2MinionInstance minion)
  {
    minionMaintainTask = ThreadPoolManager.getInstance().scheduleAi(new maintainKilledMinion(minion.getNpcId()), getKilledInterval(minion), false);
    super.notifyMinionDied(minion);
  }

  private class maintainKilledMinion implements Runnable
  {
    private int _minion;

    public maintainKilledMinion(int minion)
    {
      _minion = minion;
    }

    @Override
    public void run()
    {
      try
      {
        if(!L2RaidBossInstance.this.isDead())
        {
          MinionList list = L2RaidBossInstance.this.getMinionList();
          if(list != null)
          {
            list.spawnSingleMinionSync(_minion);
          }
        }
      }
      catch(Throwable e)
      {
        e.printStackTrace();
      }
    }
  }

  static class DamagerInfo
  {
    double damage;
    GArray<String> skills = new GArray<String>();

    public DamagerInfo(double _damage)
    {
      damage = _damage;
    }

    public DamagerInfo()
    {
      this(0);
    }

    @Override
    public String toString()
    {
      String result = String.valueOf((int) damage);
      if(skills.size() > 0)
      {
        result += " | Skills: " + skills.removeFirst();
        for(String skill : skills)
        {
          result += ", " + skill;
        }
      }
      return result;
    }

    public String toTime()
    {
      return Util.formatTime((int) ((System.currentTimeMillis() - damage) / 1000));
    }
  }
  private final FastMap<String, DamagerInfo> lastDamagers = new FastMap<String, DamagerInfo>().setShared(true);

  @Override
  public void reduceCurrentHp(double i, L2Character attacker, L2Skill skill, boolean awake, boolean standUp, boolean directHp, boolean canReflect)
  {
    if(attacker == null || attacker.getPlayer() == null || (attacker == this || i > getMaxHp() / 10) && !attacker.getPlayer().isGM())
    {
      return;
    }
    String attackerName = attacker.getPlayer().getName();
    DamagerInfo di;
    synchronized(lastDamagers)
    {
      di = lastDamagers.get(attackerName);
      if(di == null)
      {
        di = new DamagerInfo();
        lastDamagers.put(attackerName, di);
      }
      di.damage += i;
      if(skill != null && !di.skills.contains(skill.getName()))
      {
        di.skills.add(skill.getName());
      }
      if(!lastDamagers.containsKey("@"))
      {
        lastDamagers.put("@", new DamagerInfo(System.currentTimeMillis()));
      }
    }
    super.reduceCurrentHp(i, attacker, skill, awake, standUp, directHp, canReflect);
  }

  @Override
  public void doRegen()
  {
    super.doRegen();
    if(isInCombat() || !isCurrentHpFull() || lastDamagers.isEmpty())
    {
      return;
    }
    lastDamagers.clear();
  }

  @Override
  public void doDie(L2Character killer)
  {
    if(minionMaintainTask != null)
    {
      minionMaintainTask.cancel(false);
      minionMaintainTask = null;
    }
    int points = RaidBossSpawnManager.getInstance().getPoinstForRaid(getNpcId());
    if(points > 0)
    {
      calcRaidPointsReward(points);
    }
    if(this instanceof L2ReflectionBossInstance)
    {
      super.doDie(killer);
      return;
    }
    synchronized(lastDamagers)
    {
      String killTime = lastDamagers.containsKey("@") ? lastDamagers.remove("@").toTime() : "-";
      Log.add(PrintfFormat.LOG_BOSS_KILLED, new Object[]
      {
        getTypeName(), getName(), getNpcId(), killer, getX(), getY(), getZ(), killTime
      }, "bosses");
      for(String damagerName : lastDamagers.keySet())
      {
        Log.add("\tDamager [" + damagerName + "] = " + lastDamagers.get(damagerName), "bosses");
      }
      lastDamagers.clear();
    }
    if(killer.isPlayable())
    {
      L2Player player = killer.getPlayer();
      if(player.isInParty())
      {
        player.getParty().broadcastToPartyMembers(Msg.CONGRATULATIONS_YOUR_RAID_WAS_SUCCESSFUL);
      }
      else
      {
        player.sendPacket(Msg.CONGRATULATIONS_YOUR_RAID_WAS_SUCCESSFUL);
      }
      Quest q = QuestManager.getQuest(508);
      if(q != null)
      {
        String qn = q.getName();
        if(player.getClan() != null && player.getClan().getLeader().isOnline() && player.getClan().getLeader().getPlayer().getQuestState(qn) != null)
        {
          QuestState st = player.getClan().getLeader().getPlayer().getQuestState(qn);
          st.getQuest().onKill(this, st);
        }
      }
    }
    unspawnMinions();
    int boxId = 0;
    switch(getNpcId())
    {
      case 25035: // Shilens Messenger Cabrio
        boxId = 31027;
        break;
      case 25054: // Demon Kernon
        boxId = 31028;
        break;
      case 25126: // Golkonda, the Longhorn General
        boxId = 31029;
        break;
      case 25220: // Death Lord Hallate
        boxId = 31030;
        break;
    }
    if(boxId != 0)
    {
      L2NpcTemplate boxTemplate = NpcTable.getTemplate(boxId);
      if(boxTemplate != null)
      {
        final L2NpcInstance box = new L2NpcInstance(IdFactory.getInstance().getNextId(), boxTemplate);
        box.onSpawn();
        box.spawnMe(getLoc());
        box.setSpawnedLoc(getLoc());
        ThreadPoolManager.getInstance().scheduleGeneral(new Runnable()
        {
          @Override
          public void run()
          {
            box.deleteMe();
          }
        }, 60000);
      }
    }
    super.doDie(killer);
    setRaidStatus(Status.DEAD);
  }

  @SuppressWarnings("unchecked")
  private void calcRaidPointsReward(int totalPoints)
  {
    // Object groupkey (L2Party/L2CommandChannel/L2Player) | [GArray<L2Player> group, Long GroupDdamage]
    HashMap<Object, Object[]> participants = new HashMap<Object, Object[]>();
    double totalHp = getMaxHp();
    // Разбиваем игроков по группам. По возможности используем наибольшую из доступных групп: Command Channel → Party → StandAlone (сам плюс пет :)
    for(AggroInfo ai : getAggroList())
    {
      L2Player player = ai.attacker.getPlayer();
      Object key = player.getParty() != null ? player.getParty().getCommandChannel() != null ? player.getParty().getCommandChannel() : player.getParty() : player.getPlayer();
      Object[] info = participants.get(key);
      if(info == null)
      {
        info = new Object[]
        {
          new HashSet<L2Player>(), new Long(0)
        };
        participants.put(key, info);
      }
      // если это пати или командный канал то берем оттуда весь список участвующих, даже тех кто не в аггролисте
      // дубликаты не страшны - это хашсет
      if(key instanceof L2CommandChannel)
      {
        for(L2Player p : ((L2CommandChannel) key).getMembers())
        {
          if(p.isInRangeZ(this, Config.ALT_PARTY_DISTRIBUTION_RANGE))
          {
            ((HashSet<L2Player>) info[0]).add(p);
          }
        }
      }
      else if(key instanceof L2Party)
      {
        for(L2Player p : ((L2Party) key).getPartyMembers())
        {
          if(p.isInRangeZ(this, Config.ALT_PARTY_DISTRIBUTION_RANGE))
          {
            ((HashSet<L2Player>) info[0]).add(p);
          }
        }
      }
      else
      {
        ((HashSet<L2Player>) info[0]).add(player);
      }
      info[1] = ((Long) info[1]).longValue() + ai.damage;
    }
    for(Object[] groupInfo : participants.values())
    {
      HashSet<L2Player> players = (HashSet<L2Player>) groupInfo[0];
      // это та часть, которую игрок заслужил дамагом группы, но на нее может быть наложен штраф от уровня игрока
      int perPlayer = (int) Math.round(totalPoints * ((Long) groupInfo[1]).longValue() / (totalHp * players.size()));
      for(L2Player player : players)
      {
        int playerReward = perPlayer;
        // применяем штраф если нужен
        playerReward = (int) Math.round(playerReward * Experience.penaltyModifier(calculateLevelDiffForDrop(player.getLevel()), 9));
        if(playerReward == 0)
        {
          continue;
        }
        player.sendPacket(new SystemMessage(SystemMessage.YOU_HAVE_EARNED_S1_RAID_POINTS).addNumber(playerReward));
        RaidBossSpawnManager.getInstance().addPoints(player.getObjectId(), getNpcId(), playerReward);
      }
    }
    RaidBossSpawnManager.getInstance().updatePointsDb();
    RaidBossSpawnManager.getInstance().calculateRanking();
  }

  @Override
  public void onDecay()
  {
    super.onDecay();
    RaidBossSpawnManager.getInstance().onBossDespawned(this);
  }

  public void unspawnMinions()
  {
    if(hasMinions())
    {
      ThreadPoolManager.getInstance().scheduleAi(new Runnable()
      {
        @Override
        public void run()
        {
          try
          {
            removeMinions();
          }
          catch(Throwable e)
          {
            _log.log(Level.SEVERE, "", e);
            e.printStackTrace();
          }
        }
      }, getMinionUnspawnInterval(), false);
    }
  }

  @Override
  public void onSpawn()
  {
    addSkill(SkillTable.getInstance().getInfo(4045, 1)); // Resist Full Magic Attack
    RaidBossSpawnManager.getInstance().onBossSpawned(this);
    super.onSpawn();
  }

  public void setRaidStatus(RaidBossSpawnManager.Status status)
  {
    _raidStatus = status;
  }

  public RaidBossSpawnManager.Status getRaidStatus()
  {
    return _raidStatus;
  }

  @Override
  public boolean isFearImmune()
  {
    return true;
  }

  @Override
  public boolean isParalyzeImmune()
  {
    return true;
  }

  @Override
  public boolean isLethalImmune()
  {
    return true;
  }

  @Override
  public boolean hasRandomWalk()
  {
    return false;
  }

  @Override
  public boolean canChampion()
  {
    return false;
  }
}
TOP

Related Classes of l2p.gameserver.model.instances.L2RaidBossInstance$DamagerInfo

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.