Flub 1,288 Posted October 6, 2021 Report Share Posted October 6, 2021 Hey guys, this tut is for a system I created for the now leaked Platinum PS. It is a boss which is triggered when the server hits a global XP target. It then spawns in an instanced area, but the players can leaver / enter smoothly. Adapt as required, this wasn't ever intended to be a tutorial so it's more involved than others I've done. The rewards are currently XP in the chosen boss skill. Players are ranked based on damage caused to the boss. Positions 1-5 are rewarded. They are then shown a crappy interface, but it does the trick I made a new package in src.com.platinum.world.content.skillingboss Then there are two files: SkillBossConfig: package com.platinum.world.content.skillingboss; import com.platinum.model.Position; public class SkillBossConfig { // NPC ID Of the boss public static final int npcID = 6306; // The amount of time we add to the timer after it runs out public static final long timeDelay = 300000; // 5 minutes // How often will the server update players on the current XP count? public static long xpUpdateTimer = System.currentTimeMillis() + timeDelay; // 5 minutes // The spawn location of the boss public static final Position spawnPos = new Position(1861, 5222, 4); // The value that holds the global XP public static long serverXPCounter; // How much XP requred until the boss will spawn? public static long requiredServerXP = 1000000000; public static void resetTimer() { xpUpdateTimer = System.currentTimeMillis() + timeDelay; } } And SkillBossHandler package com.platinum.world.content.skillingboss; import com.platinum.model.Skill; import com.platinum.util.Misc; import com.platinum.world.World; import com.platinum.world.content.combat.CombatBuilder; import com.platinum.world.content.combat.CombatFactory; import com.platinum.world.content.discord.DiscordMessenger; import com.platinum.world.entity.impl.npc.NPC; import com.platinum.world.entity.impl.player.Player; import java.text.NumberFormat; import java.util.*; public class SkillBossHandler { private static Skill selectedSkill; public static NPC skillBoss = new NPC(SkillBossConfig.npcID, SkillBossConfig.spawnPos);; public static void handleServerXP(long XP) { if (World.getNpcs().contains(skillBoss)) { return; } if (System.currentTimeMillis() > SkillBossConfig.xpUpdateTimer && SkillBossConfig.serverXPCounter < SkillBossConfig.requiredServerXP) { SkillBossConfig.resetTimer(); long remainder = SkillBossConfig.requiredServerXP - SkillBossConfig.serverXPCounter; World.sendMessageDiscord("Global XP is currently: " + formatNumber(SkillBossConfig.serverXPCounter) + "! We need " + formatNumber(remainder) + " until the skilling boss spawns!"); } if (SkillBossConfig.serverXPCounter < SkillBossConfig.requiredServerXP) { SkillBossConfig.serverXPCounter += XP; } else { SkillBossConfig.serverXPCounter = 0; spawnSkillBoss(); } } public static String formatNumber(long number) { return NumberFormat.getInstance().format(number); } /** Spawns the Skilling Boss **/ private static void spawnSkillBoss() { selectedSkill = selectSkill(); World.register(skillBoss); World.sendMessageNonDiscord("@blu@The Skilling Boss has just spawned! Skill Selected: @red@" + selectedSkill.getFormatName() + "@blu@!"); DiscordMessenger.sendInGameMessage("The Skilling Boss has just spawned! Skill Selected: " + selectedSkill.getFormatName() + "!"); } /** Chooses a random Skill **/ private static Skill selectSkill() { return Skill.values()[Misc.exclusiveRandom(Skill.values().length)]; } /** After the NPC is killed, we calculate the damage **/ public static void calculateDamage(NPC npc) { if (npc.getCombatBuilder().getDamageMap().size() == 0) { return; } Map<Player, Integer> killers = new HashMap<>(); for (Map.Entry<Player, CombatBuilder.CombatDamageCache> entry : npc.getCombatBuilder().getDamageMap().entrySet()) { if (entry == null) { continue; } long timeout = entry.getValue().getStopwatch().elapsed(); if (timeout > CombatFactory.DAMAGE_CACHE_TIMEOUT) { continue; } Player player = entry.getKey(); if (player.getConstitution() <= 0 || !player.isRegistered()) { continue; } killers.put(player, entry.getValue().getDamage()); } npc.getCombatBuilder().getDamageMap().clear(); List<Map.Entry<Player, Integer>> result = sortEntries(killers); int count = 0; Player[] topFive = {null, null, null, null, null}; int[] topFiveDmg = {0, 0, 0, 0, 0}; int i = 0; for (Map.Entry<Player, Integer> entry : result) { Player killer = entry.getKey(); int damage = entry.getValue(); if (!Arrays.asList(topFive).equals(killer) && i <= 4) { topFive[i] = killer; topFiveDmg[i] = damage; System.out.println("Added " + killer.getUsername() + " who had dmg " + damage); } else { topFive[i] = null; topFiveDmg[i] = 0; } if (++count >= 20) { break; } i++; } String winners = ""; String fir = ""; String sec = ""; String thi = ""; String fou = ""; String fif = ""; int xpReward = 0; for (int t = 0; t <= 4; t++) { if (topFive[t] != null) { String username = topFive[t].getUsername(); String dmg = " dmg: " + Misc.formatAmount(topFiveDmg[t]); topFive[t].getPacketSender().sendInterface(297); topFive[t].getPacketSender().sendString(299, "@bla@Congratulations " + username + "!") .sendString(6158, selectedSkill.getFormatName() + " XP!") .sendString(303, "") .sendString(304, ""); switch (t) { case 0: fir = "1st: " + username + dmg; xpReward = topFiveDmg[t]; topFive[t].getPacketSender().sendString(301, "@bla@First Place!") .sendString(4444, "@gre@" + Misc.formatAmount(xpReward)); break; case 1: sec = "2nd: " + username + dmg; xpReward = topFiveDmg[t] / 2; topFive[t].getPacketSender().sendString(301, "@bla@Second Place!") .sendString(4444, "@gre@" + Misc.formatAmount(xpReward)); break; case 2: thi = "3rd: " + username + dmg; xpReward = topFiveDmg[t] / 3; topFive[t].getPacketSender().sendString(301, "@bla@Third Place!") .sendString(4444, "@gre@" + Misc.formatAmount(xpReward)); break; case 3: fou = "4th: " + username + dmg; xpReward = topFiveDmg[t] / 4; topFive[t].getPacketSender().sendString(301, "@bla@Fourth Place!") .sendString(4444, "@gre@" + Misc.formatAmount(xpReward)); break; case 4: fif = "5th: " + username + dmg; xpReward = topFiveDmg[t] / 5; topFive[t].getPacketSender().sendString(301, "@bla@Fifth Place!") .sendString(4444, "@gre@" + Misc.formatAmount(xpReward)); break; } reward(topFive[t], xpReward, selectedSkill); } winners = fir + sec + thi + fou + fif; } World.sendMessageDiscord("[Skill Boss] " + winners); World.deregister(skillBoss); } private static void reward(Player player, int xpReward, Skill skill) { if (player != null && skill != null) { player.getSkillManager().addExperience(skill, xpReward); player.getPacketSender().sendMessage("You have gained @blu@" + Misc.formatAmount(xpReward) + " @bla@" + selectedSkill.getFormatName() + " XP!"); } } static <K, V extends Comparable<? super V>> List<Map.Entry<K, V>> sortEntries(Map<K, V> map) { List<Map.Entry<K, V>> sortedEntries = new ArrayList<Map.Entry<K, V>>(map.entrySet()); Collections.sort(sortedEntries, new Comparator<Map.Entry<K, V>>() { @Override public int compare(Map.Entry<K, V> e1, Map.Entry<K, V> e2) { return e2.getValue().compareTo(e1.getValue()); } }); return sortedEntries; } } To count the global XP, add this into SkillManager.java (Inside the addExperience method) Ensure you add it after any multipliers / XP reductions so that 2x XP is included. SkillBossHandler.handleServerXP(experience); I used a location for our implementation since it's the cleanest way and keeps things organized (Locations.java) SKILLING_BOSS(new int[] { 1856, 1867 }, new int[] { 5214, 5229 }, true, true, true, false, true, true) { @Override public void logout(Player player) { if (player.getPosition().getZ() == 4) { player.moveTo(player.getPosition().getX(), player.getPosition().getY(), 0); } } @Override public void leave(Player player) { if (player.getPosition().getZ() == 4) { player.moveTo(player.getPosition().getX(), player.getPosition().getY(), 0); } } @Override public void enter(Player player) { if (World.getNpcs().contains(SkillBossHandler.skillBoss)) { player.moveTo(player.getPosition().getX(), player.getPosition().getY(), 4); } } @Override public boolean handleKilledNPC(Player killer, NPC npc) { if (npc == SkillBossHandler.skillBoss) { SkillBossHandler.calculateDamage(SkillBossHandler.skillBoss); return true; } return false; } }, Thanks bois 1 Link to comment Share on other sites More sharing options...
dangercroc 0 Posted October 10, 2021 Report Share Posted October 10, 2021 i like your work Link to comment Share on other sites More sharing options...
kishen17 0 Posted November 13, 2021 Report Share Posted November 13, 2021 very interesting Link to comment Share on other sites More sharing options...
xBradyx 1 Posted December 2, 2021 Report Share Posted December 2, 2021 Looks good. 🙂 Link to comment Share on other sites More sharing options...
TestySauce 1 Posted December 2, 2021 Report Share Posted December 2, 2021 Thanks will use Link to comment Share on other sites More sharing options...
shadowisdom 1 Posted February 6, 2022 Report Share Posted February 6, 2022 thanks for this Link to comment Share on other sites More sharing options...
Ary3x 0 Posted February 14, 2022 Report Share Posted February 14, 2022 will be using thanks Link to comment Share on other sites More sharing options...
Boydie96 5 Posted March 1, 2022 Report Share Posted March 1, 2022 Thanks! Link to comment Share on other sites More sharing options...
QueenEmsy 0 Posted April 13, 2022 Report Share Posted April 13, 2022 This is pretty freakin cool! Link to comment Share on other sites More sharing options...
Snooperal 0 Posted April 17, 2022 Report Share Posted April 17, 2022 could actually be useful Link to comment Share on other sites More sharing options...
0117be 66 Posted June 2, 2022 Report Share Posted June 2, 2022 I like the idea of this.. max exp announcment... very nice Link to comment Share on other sites More sharing options...
nsin25 0 Posted February 7, 2023 Report Share Posted February 7, 2023 Great idea, thank you! Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now