U3Games

Games | Desarrollo & Soporte => L2 | Sección de Servidores => Lineage => L2 | Implementaciones => Mensaje iniciado por: Jerry en May 09, 2026, 05:30 PM

Título: RaidBoss Damage Ranking System - rus aCis 3.5
Publicado por: Jerry en May 09, 2026, 05:30 PM
(https://i.ibb.co/0pJvLvQd/image.png)

Básicamente, es un sistema que gestiona un ranking de jugadores que participan en la muerte de un raid boss y anuncia los resultados globalmente al finalizar cada boss.

El sistema no guarda información en base de datos. Su funcionamiento consiste en detectar qué jugadores están atacando al boss y almacenar estadísticas como:

- Mayor daño realizado en un solo golpe.
- Daño total acumulado al jefe.
- Cantidad de golpes realizados.

Al morir el jefe, se genera automáticamente un TOP 10 con los jugadores que más daño total hicieron al boss, mostrando también el golpe más alto registrado entre ellos.

Criterios del ranking:

- Primer criterio: mayor daño total acumulado.
- En caso de empate: mayor cantidad de golpes.
-Si continúa el empate: mayor golpe individual realizado.

El sistema no entrega recompensas; únicamente realiza el anuncio global mostrando el nombre de los jugadores destacados.


diff --git a/aCis_gameserver/java/by/leonardoalves/mods/RaidDamage/RaidDamageEntry.java b/aCis_gameserver/java/by/leonardoalves/mods/RaidDamage/RaidDamageEntry.java
new file mode 100644
index 0000000..b9b3094
--- /dev/null
+++ b/aCis_gameserver/java/by/leonardoalves/mods/RaidDamage/RaidDamageEntry.java
@@ -0,0 +1,60 @@
+package by.leonardoalves.mods.RaidDamage;
+
+/**
+ * @author Leonardo Alves
+ *
+ */
+public class RaidDamageEntry implements Comparable<RaidDamageEntry>
+{
+    private final int _playerObjectId;
+    private final int _raidId;
+   
+    private long _totalDamage;
+    private int _hitCount;
+    private long _maxHit;
+   
+    public RaidDamageEntry(int playerObjectId, int raidId) {
+        _playerObjectId = playerObjectId;
+        _raidId = raidId;
+    }
+   
+    public void registerHit(long damage) {
+        _totalDamage += damage;
+        _hitCount++;
+       
+        if (damage > _maxHit)
+            _maxHit = damage;
+    }
+    public int getPlayerId()
+    {
+        return _playerObjectId;
+    }
+
+    public long getTotalDamage()
+    {
+        return _totalDamage;
+    }
+   
+    public long getMaxHit() {
+        return _maxHit;
+    }
+   
+    public int getHitCount()
+    {
+        return _hitCount;
+    }
+    @Override
+    public int compareTo(RaidDamageEntry other) {
+        int result = Long.compare(other._totalDamage, this._totalDamage);
+       
+        if(result != 0)
+            return result;
+       
+        result = Integer.compare(other._hitCount, this._hitCount);
+       
+        if(result != 0)
+            return result;
+       
+        return Long.compare(other._maxHit, this._maxHit);
+    }
+}
diff --git a/aCis_gameserver/java/by/leonardoalves/mods/RaidDamage/RaidDamageTracker.java b/aCis_gameserver/java/by/leonardoalves/mods/RaidDamage/RaidDamageTracker.java
new file mode 100644
index 0000000..031f8fb
--- /dev/null
+++ b/aCis_gameserver/java/by/leonardoalves/mods/RaidDamage/RaidDamageTracker.java
@@ -0,0 +1,30 @@
+package by.leonardoalves.mods.RaidDamage;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Leonardo Alves
+ *
+ */
+public class RaidDamageTracker
+{
+    private final int _raidId;
+    private final Map<Integer, RaidDamageEntry> _entries = new HashMap<>();
+   
+    public RaidDamageTracker(int raidId) {
+        _raidId = raidId;
+    }
+    public void addDamage(int playerObjectId, long damage) {
+        RaidDamageEntry entry = _entries.computeIfAbsent(playerObjectId, id -> new RaidDamageEntry(id, _raidId));
+        entry.registerHit(damage);
+    }
+    public List<RaidDamageEntry> getRanking(){
+        List<RaidDamageEntry> ranking = new ArrayList<>(_entries.values());
+        Collections.sort(ranking);
+        return ranking;
+    }
+}
diff --git a/aCis_gameserver/java/net/sf/l2j/gameserver/model/actor/instance/RaidBoss.java b/aCis_gameserver/java/net/sf/l2j/gameserver/model/actor/instance/RaidBoss.java
new file mode 100644
index 0000000..e1dbf8f
--- /dev/null
+++ b/aCis_gameserver/java/net/sf/l2j/gameserver/model/actor/instance/RaidBoss.java
@@ -0,0 +1,204 @@
import net.sf.l2j.gameserver.model.group.Party;
import net.sf.l2j.gameserver.model.spawn.ASpawn;
import net.sf.l2j.gameserver.network.SystemMessageId;
import net.sf.l2j.gameserver.network.serverpackets.PlaySound;
import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
import net.sf.l2j.gameserver.skills.L2Skill;
+import by.leonardoalves.mods.RaidDamage.RaidDamageEntry;
+import by.leonardoalves.mods.RaidDamage.RaidDamageTracker;
+
/**
 * This class manages all classic raid bosses.<br>
 * <br>
 * Raid Bosses (RB) are mobs which are supposed to be defeated by a party of several players. It extends most of {@link Monster} aspects.<br>
 * <br>
 * They automatically teleport if out of their initial spawn area, and can randomly attack a Player from their Hate List once attacked.<br>
 * <br>
 * Their looting rights are affected by {@link CommandChannel}s. The first who attacks got the priority over loots. Those rights are lost if no attack has been done for 900sec.
 */
public class RaidBoss extends Monster
{
    private ScheduledFuture<?> _maintenanceTask;
+    private final RaidDamageTracker _damageTracker;
+   
    public RaidBoss(int objectId, NpcTemplate template)
    {
        super(objectId, template);
+        _damageTracker = new RaidDamageTracker(objectId);
+       
        setRaidRelated();
    }
   
+    @SuppressWarnings("null")
+    @Override
+    public void reduceCurrentHp(double damage, Creature attacker, boolean awake, boolean isDOT, L2Skill skill)
+    {
+        super.reduceCurrentHp(damage, attacker, awake, isDOT, skill);
+       
+        if (attacker instanceof Summon || attacker == null || damage <= 0)
+            return;
+       
+        if (attacker != null && damage > 0)
+        {
+            Player player = attacker.getActingPlayer();
+            if (player != null)
+            {   
+                _damageTracker.addDamage(player.getObjectId(), (long) damage);
+            }
+        }
+    }
   
    @Override
    public boolean doDie(Creature killer)
    {
        if (!super.doDie(killer))
            return false;
       
        if (_maintenanceTask != null)
        {
            _maintenanceTask.cancel(false);
            _maintenanceTask = null;
        }
       
+        List<RaidDamageEntry> ranking = _damageTracker.getRanking();
+        announceTopDamage(ranking);
        if (killer != null)
        {
            final Player player = killer.getActingPlayer();
            if (player != null)
            {
                broadcastPacket(SystemMessage.getSystemMessage(SystemMessageId.RAID_WAS_SUCCESSFUL));
                broadcastPacket(new PlaySound("systemmsg_e.1209"));
               
                final Party party = player.getParty();
                if (party != null)
                {
                    for (Player member : party.getMembers())
                    {
                        RaidPointManager.getInstance().addPoints(member, getNpcId(), (getStatus().getLevel() / 2) + Rnd.get(-5, 5));
                        if (member.isNoble())
                            HeroManager.getInstance().setRBkilled(member.getObjectId(), getNpcId());
                    }
                }
                else
                {
                    RaidPointManager.getInstance().addPoints(player, getNpcId(), (getStatus().getLevel() / 2) + Rnd.get(-5, 5));
                    if (player.isNoble())
                        HeroManager.getInstance().setRBkilled(player.getObjectId(), getNpcId());
                }
            }
        }
        // TODO implement SpawnManager or ASpawn notification
        // RaidBossManager.getInstance().onDeath(this);
        return true;
    }
+    private void announceTopDamage(List<RaidDamageEntry> ranking)
+    {
+        World.announceToOnlinePlayers("== Top Damage - " + getName() + " ==");
+
+        for (int i = 0; i < Math.min(10, ranking.size()); i++)
+        {
+            RaidDamageEntry entry = ranking.get(i);
+            Player p = World.getInstance().getPlayer(entry.getPlayerId());
+
+            if (p != null)
+            {
+                World.announceToOnlinePlayers(
+                    String.format(
+                        "%d° %s - Total: %.2f | Maior Hit: %.2f",
+                        (i + 1),
+                        p.getName(),
+                        (double) entry.getTotalDamage(),
+                        (double) entry.getMaxHit()
+                    )
+                );
+            }
+        }
+    }
+
+
    @Override
    public void deleteMe()
    {
        if (_maintenanceTask != null)
        {
            _maintenanceTask.cancel(false);
            _maintenanceTask = null;
        }
       
        super.deleteMe();
    }
}

By LEONARDO ALVES