Raidboss Announcer is a mod that allows you to announce the RaidBoss to all players online.
Tested in Lucera revs. For any other rev, contact us here#===================================#
#
# GIRAN FORGE
# https://giranforge.com/
#
# This file goes into gameserver/config/custom/giranforge.properties
#===================================#
#===================================#
# Raidboss Announcements
#===================================#
# Enable/Disable the announcement of the RaidBoss
ENABLE_RB_ANNOUNCEMENTS=true
# Minimum level of the RaidBoss to trigger the announcement
MIN_RB_LEVEL=75
# Distance from RaidBoss where a player should receive the announcement
# If set to -1, the announcement will be shown to all players online
DISTANCE_TO_ANNOUNCE=5000
# This will show a nice message in players screen if true
SHOW_SCREEN_MESSAGE=true
# Time in ms to show the screen message
SHOW_SCREEN_MESSAGE_TIME=5000
package services;
import l2.commons.configuration.ExProperties;
import l2.gameserver.Announcements;
import l2.gameserver.listener.actor.OnAttackListener;
import l2.gameserver.listener.actor.OnDeathListener;
import l2.gameserver.model.Creature;
import l2.gameserver.model.Player;
import l2.gameserver.model.instances.RaidBossInstance;
import l2.gameserver.model.actor.listener.CharListenerList;
import l2.gameserver.network.l2.components.ChatType;
import l2.gameserver.network.l2.components.IStaticPacket;
import l2.gameserver.network.l2.components.NpcString;
import l2.gameserver.network.l2.s2c.ExShowScreenMessage;
import l2.gameserver.network.l2.s2c.Say2;
import l2.gameserver.scripts.ScriptFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
public class BossAnnouncement implements OnAttackListener, OnDeathListener, ScriptFile {
protected static final Logger _log = LoggerFactory.getLogger(BossAnnouncement.class);
private static final BossAnnouncement INSTANCE = new BossAnnouncement();
private final Map<Integer, Map<Integer, Boolean>> rbPercentages = new HashMap<>();
private final Map<Integer, Boolean> isBeingAttacked = new HashMap<>();
private static final String CONFIG_FILE = "config/custom/giranforge.properties";
private static boolean ENABLE_RB_ANNOUNCEMENTS = true;
private static int MIN_RB_LEVEL = 75;
private static int DISTANCE_TO_ANNOUNCE = 5000; /// -1 to announce to everyone
private static boolean SHOW_SCREEN_MESSAGE = false;
private static int SHOW_SCREEN_MESSAGE_TIME = 5000;
public static void loadConfigs() {
ExProperties config = initProperties(CONFIG_FILE);
ENABLE_RB_ANNOUNCEMENTS = Boolean.parseBoolean(config.getProperty("ENABLE_RB_ANNOUNCEMENTS", "true"));
MIN_RB_LEVEL = Integer.parseInt(config.getProperty("MIN_RB_LEVEL", "15"));
DISTANCE_TO_ANNOUNCE = Integer.parseInt(config.getProperty("DISTANCE_TO_ANNOUNCE", "30"));
SHOW_SCREEN_MESSAGE = Boolean.parseBoolean(config.getProperty("SHOW_SCREEN_MESSAGE", "false"));
SHOW_SCREEN_MESSAGE_TIME = Integer.parseInt(config.getProperty("SHOW_SCREEN_MESSAGE_TIME", "5000"));
}
public static ExProperties initProperties(String filename) {
ExProperties result = new ExProperties();
try {
result.load(new File(filename));
} catch (IOException ignored) {}
return result;
}
@Override
public void onAttack(Creature attacker, Creature target) {
if (attacker instanceof Player && target instanceof RaidBossInstance raidBoss) {
if (raidBoss.getLevel() < MIN_RB_LEVEL) {
return;
}
double currentHp = raidBoss.getCurrentHp();
double maxHp = raidBoss.getMaxHp();
int hpPercentage = (int) ((currentHp / maxHp) * 100);
if (!isBeingAttacked.containsKey(target.getObjectId())) {
isBeingAttacked.put(target.getObjectId(), true);
String message = "Raid Boss: " + raidBoss.getName() + " has been attacked!";
announceToAll(message, raidBoss);
}
Map<Integer, Boolean> notifiedPercentages = rbPercentages.computeIfAbsent(raidBoss.getObjectId(), k -> new HashMap<>());
String message = null;
if (hpPercentage <= 50 && !notifiedPercentages.containsKey(50)) {
notifiedPercentages.put(50, true);
message = "Attention! Raid Boss: " + raidBoss.getName() + " has dropped to " + 50 + "% HP!";
} else if (hpPercentage <= 25 && !notifiedPercentages.containsKey(25)){
notifiedPercentages.put(25, true);
message = "Attention! Raid Boss: " + raidBoss.getName() + " has dropped to " + 25 + "% HP!";
} else if (hpPercentage <= 10 && !notifiedPercentages.containsKey(10)){
notifiedPercentages.put(10, true);
message = "Attention! Raid Boss: " + raidBoss.getName() + " has dropped to " + 10 + "% HP!";
}
if(message != null){
announceToAll(message, raidBoss);
}
}
}
@Override
public void onDeath(Creature actor, Creature killer) {
if (actor instanceof RaidBossInstance raidBoss) {
if (raidBoss.getLevel() < MIN_RB_LEVEL) {
return;
}
String message = "Raid Boss: " + raidBoss.getName() + " has been defeated!";
announceToAll(message, raidBoss);
rbPercentages.remove(raidBoss.getObjectId());
isBeingAttacked.remove(raidBoss.getObjectId());
}
}
private void announceToAll(String message, RaidBossInstance raidBoss) {
Say2 announcement = new Say2(0, ChatType.ANNOUNCEMENT, "", message);
IStaticPacket screenMessage = createScreenMessage(message, SHOW_SCREEN_MESSAGE_TIME);
_log.info(screenMessage.toString());
_log.info(String.valueOf(SHOW_SCREEN_MESSAGE));
if(DISTANCE_TO_ANNOUNCE == -1) {
Announcements.getInstance().announceToAll(announcement);
if(SHOW_SCREEN_MESSAGE){
Announcements.getInstance().announceToAll(screenMessage);
}
return;
}
raidBoss.getAroundCharacters(DISTANCE_TO_ANNOUNCE, 200).forEach(player -> {
player.sendPacket(announcement);
if(SHOW_SCREEN_MESSAGE){
player.sendPacket(screenMessage);
}
});
}
private IStaticPacket createScreenMessage(String message, Integer duration){
return new ExShowScreenMessage(
NpcString.NONE,
duration,
ExShowScreenMessage.ScreenMessageAlign.TOP_CENTER,
true,
ExShowScreenMessage.STRING_TYPE,
-1,
true,
message
);
}
@Override
public void onLoad() {
if(ENABLE_RB_ANNOUNCEMENTS) {
loadConfigs();
CharListenerList.addGlobal(INSTANCE);
_log.info("===================================");
_log.info("Raidboss Announcements loaded");
_log.info("===================================");
}
}
@Override
public void onReload() {
onShutdown();
onLoad();
}
@Override
public void onShutdown() {
CharListenerList.removeGlobal(INSTANCE);
}
}