diff --git a/TwosideKeeper.jar b/TwosideKeeper.jar index 496d94f..5ec708c 100644 Binary files a/TwosideKeeper.jar and b/TwosideKeeper.jar differ diff --git a/src/sig/plugin/TwosideKeeper/ActionBarBuffUpdater.java b/src/sig/plugin/TwosideKeeper/ActionBarBuffUpdater.java index 5bb2476..fb20f88 100644 --- a/src/sig/plugin/TwosideKeeper/ActionBarBuffUpdater.java +++ b/src/sig/plugin/TwosideKeeper/ActionBarBuffUpdater.java @@ -100,7 +100,7 @@ public class ActionBarBuffUpdater{ } effectString.append(ConvertBuffAmplifierToIcon(b.getAmplifier())); effectString.append(" "); - if (b.getRemainingBuffTime()<=200) { + if (b.getRemainingBuffTime()<=200 || b.getDisplayTimerAlways()) { effectString.append(ConvertBuffTimeToIcon(b.getRemainingBuffTime())); } effectString.append(" "); @@ -160,6 +160,9 @@ public class ActionBarBuffUpdater{ } private static String ConvertBuffTimeToIcon(long remainingBuffTime) { + if (remainingBuffTime>200) { + return Long.toString(remainingBuffTime/20); + } else if (remainingBuffTime>180) { return "➓"; } else diff --git a/src/sig/plugin/TwosideKeeper/Boss/EliteZombie.java b/src/sig/plugin/TwosideKeeper/Boss/EliteZombie.java index 1dbdceb..74bde3c 100644 --- a/src/sig/plugin/TwosideKeeper/Boss/EliteZombie.java +++ b/src/sig/plugin/TwosideKeeper/Boss/EliteZombie.java @@ -32,6 +32,7 @@ import sig.plugin.TwosideKeeper.CustomDamage; import sig.plugin.TwosideKeeper.EliteMonster; import sig.plugin.TwosideKeeper.MonsterController; import sig.plugin.TwosideKeeper.TwosideKeeper; +import sig.plugin.TwosideKeeper.HelperStructures.LivingEntityDifficulty; import sig.plugin.TwosideKeeper.HelperStructures.Loot; import sig.plugin.TwosideKeeper.HelperStructures.MonsterDifficulty; import sig.plugin.TwosideKeeper.HelperStructures.PlayerMode; @@ -482,7 +483,8 @@ public class EliteZombie extends EliteMonster{ Monster nm = (Monster)m.getWorld().spawnEntity(getNearbyFreeLocation(m.getLocation()),choice); Player target = targetlist.get((int)(Math.random() * targetlist.size())); nm.setTarget(target); - MonsterController.convertMonster(nm, MonsterDifficulty.HELLFIRE); + //MonsterController.convertMonster(nm, MonsterDifficulty.HELLFIRE); + MonsterController.convertLivingEntity(nm, LivingEntityDifficulty.HELLFIRE); } if (CustomDamage.getPercentHealthRemaining(m)<10) { Player target = targetlist.get((int)(Math.random() * targetlist.size())); @@ -491,7 +493,8 @@ public class EliteZombie extends EliteMonster{ nm.setPowered(true); } nm.setTarget(target); - MonsterController.convertMonster(nm, MonsterDifficulty.HELLFIRE); + //MonsterController.convertMonster(nm, MonsterDifficulty.HELLFIRE); + MonsterController.convertLivingEntity(nm, LivingEntityDifficulty.HELLFIRE); } } diff --git a/src/sig/plugin/TwosideKeeper/Buff.java b/src/sig/plugin/TwosideKeeper/Buff.java index 238f20f..072f527 100644 --- a/src/sig/plugin/TwosideKeeper/Buff.java +++ b/src/sig/plugin/TwosideKeeper/Buff.java @@ -18,6 +18,7 @@ public class Buff { private String icon; private boolean isGoodBuff; //If false, it's a debuff. private boolean permanentBuff; //Whether or not this buff/debuff cannot be removed by normal means. + private boolean displayTimer; /** * Creates a new Buff structure. @@ -36,6 +37,7 @@ public class Buff { this.icon=icon; this.isGoodBuff=isGoodBuff; this.permanentBuff=false; + this.displayTimer=false; } /** @@ -56,6 +58,7 @@ public class Buff { this.icon=icon; this.isGoodBuff=isGoodBuff; this.permanentBuff=permanentBuff; + this.displayTimer=false; } public static boolean hasBuffInHashMap(LivingEntity l, String name) { @@ -139,6 +142,14 @@ public class Buff { } } + public void setDisplayTimerAlways(boolean displayTimerAlways) { + this.displayTimer=displayTimerAlways; + } + + public boolean getDisplayTimerAlways() { + return displayTimer; + } + public static void addBuff(LivingEntity l, String name, Buff buff) { addBuff(l,name,buff,false); } diff --git a/src/sig/plugin/TwosideKeeper/Events/EntityChannelCastEvent.java b/src/sig/plugin/TwosideKeeper/Events/EntityChannelCastEvent.java new file mode 100644 index 0000000..3e77a3d --- /dev/null +++ b/src/sig/plugin/TwosideKeeper/Events/EntityChannelCastEvent.java @@ -0,0 +1,34 @@ +package sig.plugin.TwosideKeeper.Events; + +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class EntityChannelCastEvent extends Event{ + private LivingEntity l; + private String abilityName; + private static final HandlerList handlers = new HandlerList(); + + public EntityChannelCastEvent(LivingEntity l, String abilityName) { + this.l=l; + this.abilityName=abilityName; + } + + public LivingEntity getLivingEntity() { + return l; + } + + public String getAbilityName() { + return abilityName; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } + +} diff --git a/src/sig/plugin/TwosideKeeper/HelperStructures/Channel.java b/src/sig/plugin/TwosideKeeper/HelperStructures/Channel.java new file mode 100644 index 0000000..3c6a2be --- /dev/null +++ b/src/sig/plugin/TwosideKeeper/HelperStructures/Channel.java @@ -0,0 +1,151 @@ +package sig.plugin.TwosideKeeper.HelperStructures; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.boss.BarColor; +import org.bukkit.boss.BarFlag; +import org.bukkit.boss.BarStyle; +import org.bukkit.boss.BossBar; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; + +import sig.plugin.TwosideKeeper.LivingEntityStructure; +import sig.plugin.TwosideKeeper.PlayerStructure; +import sig.plugin.TwosideKeeper.TwosideKeeper; +import sig.plugin.TwosideKeeper.Events.EntityChannelCastEvent; +import sig.plugin.TwosideKeeper.HelperStructures.Common.GenericFunctions; + +public class Channel { + LivingEntity l; + String channelName; + int duration; + long channelStartTime; + BossBar channelBar; + boolean cancelled=false; + + public Channel(LivingEntity l, String spellName, int tickDuration) { + this.l=l; + this.channelName=spellName; + this.duration=tickDuration; + this.channelStartTime=TwosideKeeper.getServerTickTime(); + if (l instanceof Player) { + Player p = (Player)l; + channelBar = l.getServer().createBossBar(ChatColor.YELLOW+channelName, BarColor.YELLOW, BarStyle.SOLID, BarFlag.CREATE_FOG); + channelBar.addPlayer(p); + UpdateBossBar(); + PlayerStructure pd = PlayerStructure.GetPlayerStructure(p); + pd.currentChannel=this; + } else { + UpdateMobChannelingBar(l); + l.setCustomNameVisible(true); + LivingEntityStructure les = LivingEntityStructure.GetLivingEntityStructure(l); + les.currentChannel=this; + } + GenericFunctions.addSuppressionTime(l, duration); + AddToStructure(); + } + + public static Channel createNewChannel(LivingEntity l, String spellName, int channelDuration){ + return new Channel(l,spellName,channelDuration); + } + + public static boolean isChanneling(LivingEntity l) { + if (l instanceof Player) { + PlayerStructure pd = PlayerStructure.GetPlayerStructure((Player)l); + return pd.currentChannel!=null; + } else { + LivingEntityStructure les = LivingEntityStructure.GetLivingEntityStructure(l); + return les.currentChannel!=null; + } + } + + public static void stopChanneling(LivingEntity l) { + if (isChanneling(l)) { + Channel c = getCurrentChannel(l); + c.setCancelled(true); + } + } + + public static Channel getCurrentChannel(LivingEntity l) { + if (isChanneling(l)) { + if (l instanceof Player) { + PlayerStructure pd = PlayerStructure.GetPlayerStructure((Player)l); + return pd.currentChannel; + } else { + LivingEntityStructure les = LivingEntityStructure.GetLivingEntityStructure(l); + return les.currentChannel; + } + } else { + return null; + } + } + + private void AddToStructure() { + TwosideKeeper.channels.add(this); + } + + private void UpdateMobChannelingBar(LivingEntity l) { + LivingEntityStructure.setChannelingBar(l, getMobChannelingBar()); + } + + private void UpdateBossBar() { + long tickTimeChanneled = TwosideKeeper.getServerTickTime()-channelStartTime; + double ratio = (double)tickTimeChanneled/duration; + channelBar.setProgress(ratio); + } + + private String getMobChannelingBar() { + StringBuilder sb = new StringBuilder(); + sb.append(ChatColor.YELLOW); + sb.append(channelName); + sb.append("["); + long tickTimeChanneled = TwosideKeeper.getServerTickTime()-channelStartTime; + double ratio = (double)tickTimeChanneled/duration; + int bars = (int)(ratio*10); + for (int i=0;i0) { + l.setCustomNameVisible(false); + } + } + EntityChannelCastEvent ev = new EntityChannelCastEvent(l,channelName); + Bukkit.getPluginManager().callEvent(ev); + return false; + } else { + if (channelBar!=null) { + UpdateBossBar(); + } else { + UpdateMobChannelingBar(l); + LivingEntityStructure.UpdateMobName(l); + } + return true; + } + } +} diff --git a/src/sig/plugin/TwosideKeeper/HelperStructures/Common/GenericFunctions.java b/src/sig/plugin/TwosideKeeper/HelperStructures/Common/GenericFunctions.java index a01e50e..f51320b 100644 --- a/src/sig/plugin/TwosideKeeper/HelperStructures/Common/GenericFunctions.java +++ b/src/sig/plugin/TwosideKeeper/HelperStructures/Common/GenericFunctions.java @@ -4802,6 +4802,8 @@ public class GenericFunctions { if (ent instanceof Player) { Player p = (Player)ent; aPlugin.API.setPlayerSpeedMultiplier(p, 0); + p.setWalkSpeed(0f); + p.setFlying(false); } GlowAPI.setGlowing(ent, GlowAPI.Color.BLACK, Bukkit.getOnlinePlayers()); } diff --git a/src/sig/plugin/TwosideKeeper/HelperStructures/LivingEntityDifficulty.java b/src/sig/plugin/TwosideKeeper/HelperStructures/LivingEntityDifficulty.java index d4f7445..cb3af80 100644 --- a/src/sig/plugin/TwosideKeeper/HelperStructures/LivingEntityDifficulty.java +++ b/src/sig/plugin/TwosideKeeper/HelperStructures/LivingEntityDifficulty.java @@ -23,17 +23,23 @@ import sig.plugin.TwosideKeeper.HelperStructures.Common.GenericFunctions; import sig.plugin.TwosideKeeper.HolidayEvents.Christmas; public enum LivingEntityDifficulty { - NORMAL(0), - DANGEROUS(500), - DEADLY(1000), - HELLFIRE(5000), - ELITE(10000), - END(6000); + NORMAL(0,""), + DANGEROUS(500,ChatColor.DARK_AQUA+"Dangerous"), + DEADLY(1000,ChatColor.GOLD+"Deadly"), + HELLFIRE(5000,ChatColor.DARK_RED+"Hellfire"), + ELITE(10000,ChatColor.DARK_PURPLE+"Elite"), + END(6000,ChatColor.DARK_BLUE+""+ChatColor.MAGIC+"End"); int rating; + String difficultyString; - LivingEntityDifficulty(int rating) { + LivingEntityDifficulty(int rating,String diffString) { this.rating=rating; + this.difficultyString=diffString; + } + + public String getDifficultyString() { + return difficultyString; } /*private ItemStack Artifact() { diff --git a/src/sig/plugin/TwosideKeeper/HelperStructures/MonsterDifficulty.java b/src/sig/plugin/TwosideKeeper/HelperStructures/MonsterDifficulty.java index bf976a9..d9ae988 100644 --- a/src/sig/plugin/TwosideKeeper/HelperStructures/MonsterDifficulty.java +++ b/src/sig/plugin/TwosideKeeper/HelperStructures/MonsterDifficulty.java @@ -24,17 +24,27 @@ import sig.plugin.TwosideKeeper.HelperStructures.Common.GenericFunctions; @Deprecated public enum MonsterDifficulty { - NORMAL, - DANGEROUS, - DEADLY, - HELLFIRE, - ELITE, - END; + NORMAL(LivingEntityDifficulty.NORMAL), + DANGEROUS(LivingEntityDifficulty.DANGEROUS), + DEADLY(LivingEntityDifficulty.DEADLY), + HELLFIRE(LivingEntityDifficulty.HELLFIRE), + ELITE(LivingEntityDifficulty.ELITE), + END(LivingEntityDifficulty.END); + + LivingEntityDifficulty diff; + + MonsterDifficulty(LivingEntityDifficulty diff) { + this.diff=diff; + } /*private ItemStack Artifact() { sig.plugin.TwosideKeeper.Artifact.createArtifactItem(ArtifactItem.ARTIFACT_ESSENCE,3); return null; }*/ + + public LivingEntityDifficulty getLivingEntityDifficultyEquivalent() { + return this.diff; + } public List RandomizeDrops(double dropmult, boolean isBoss, boolean isRanger, Entity damager, Monster m) { return RandomizeDrops(dropmult,isBoss,false,isRanger,damager,m); diff --git a/src/sig/plugin/TwosideKeeper/HelperStructures/Utils/PlayerUtils.java b/src/sig/plugin/TwosideKeeper/HelperStructures/Utils/PlayerUtils.java index 7fc57a3..ab76c5a 100644 --- a/src/sig/plugin/TwosideKeeper/HelperStructures/Utils/PlayerUtils.java +++ b/src/sig/plugin/TwosideKeeper/HelperStructures/Utils/PlayerUtils.java @@ -3,10 +3,18 @@ package sig.plugin.TwosideKeeper.HelperStructures.Utils; import org.bukkit.entity.Player; import sig.plugin.TwosideKeeper.PlayerStructure; +import sig.plugin.TwosideKeeper.TwosideKeeper; +import sig.plugin.TwosideKeeper.HelperStructures.Common.GenericFunctions; public class PlayerUtils { public static boolean PlayerIsInCombat(Player p) { PlayerStructure pd = PlayerStructure.GetPlayerStructure(p); return (pd.target!=null && pd.target.isValid() && !pd.target.isDead() && pd.target.getLocation().getWorld().equals(p.getWorld()) && pd.target.getLocation().distanceSquared(p.getLocation())<256); } + public static boolean cooldownAvailable(long basetimer, int cooldown, Player p) { + return (basetimer+GenericFunctions.GetModifiedCooldown(cooldown, p)<=TwosideKeeper.getServerTickTime()); + } + public static long cooldownTimeRemaining(long basetimer, int cooldown, Player p) { + return (basetimer+GenericFunctions.GetModifiedCooldown(cooldown, p))-TwosideKeeper.getServerTickTime(); + } } diff --git a/src/sig/plugin/TwosideKeeper/LivingEntityStructure.java b/src/sig/plugin/TwosideKeeper/LivingEntityStructure.java index d00ba9a..8c97447 100644 --- a/src/sig/plugin/TwosideKeeper/LivingEntityStructure.java +++ b/src/sig/plugin/TwosideKeeper/LivingEntityStructure.java @@ -11,6 +11,8 @@ import org.bukkit.entity.Monster; import org.bukkit.entity.Player; import org.inventivetalent.glow.GlowAPI; +import sig.plugin.TwosideKeeper.HelperStructures.Channel; +import sig.plugin.TwosideKeeper.HelperStructures.LivingEntityDifficulty; import sig.plugin.TwosideKeeper.HelperStructures.Common.GenericFunctions; import sig.plugin.TwosideKeeper.HelperStructures.Utils.DebugUtils; @@ -40,6 +42,7 @@ public class LivingEntityStructure { public long lastCrippleTick=0; public long lastBurnTick=0; public float MoveSpeedMultBeforeCripple=1f; + public Channel currentChannel=null; final static String MODIFIED_NAME_CODE = ChatColor.RESET+""+ChatColor.RESET+""+ChatColor.RESET; final static String MODIFIED_NAME_DELIMITER = ChatColor.RESET+";"+ChatColor.RESET; @@ -71,7 +74,18 @@ public class LivingEntityStructure { //TwosideKeeper.log("Custom Name is "+m.getCustomName(), 0); if (!isModifiedName(m.getCustomName())) { //TwosideKeeper.log(" NOT A MODIFIED NAME! "+m.getCustomName(), 0); - return m.getCustomName(); + //See if it's an old version of the difficulty naming system. + LivingEntityDifficulty diff = MonsterController.getOldLivingEntityDifficulty(m); + if (diff!=null) { + String diffname = diff.getDifficultyString(); + String basename = m.getCustomName().replace(diffname+" ", ""); + difficulty_modifier = diffname; + //TwosideKeeper.log(" Set Difficulty to "+difficulty_modifier, 0); + //TwosideKeeper.log(" Set Base Name to "+basename, 0); + return basename; + } else { + return m.getCustomName(); + } } else { String[] splitter = m.getCustomName().split(MODIFIED_NAME_DELIMITER); difficulty_modifier = splitter[0]; @@ -222,7 +236,7 @@ public class LivingEntityStructure { GenericFunctions.RefreshBuffColor(m, Buff.getBuff(m, "DeathMark").getAmplifier()); } CustomDamage.appendDebuffsToName(m); - if (les.suffix_bar.length()>0) { + if (les.suffix_bar.length()>0 || les.prefix.length()>0) { m.setCustomNameVisible(true); } m.setCustomName(actualName); @@ -262,4 +276,8 @@ public class LivingEntityStructure { LivingEntityStructure les = LivingEntityStructure.GetLivingEntityStructure(l); return les.base_name; } + public static void setChannelingBar(LivingEntity l, String barString) { + LivingEntityStructure les = LivingEntityStructure.GetLivingEntityStructure(l); + les.prefix = barString; + } } diff --git a/src/sig/plugin/TwosideKeeper/MonsterController.java b/src/sig/plugin/TwosideKeeper/MonsterController.java index fddcd6e..d109c7b 100644 --- a/src/sig/plugin/TwosideKeeper/MonsterController.java +++ b/src/sig/plugin/TwosideKeeper/MonsterController.java @@ -862,6 +862,32 @@ public class MonsterController { } } + @Deprecated + public static LivingEntityDifficulty getOldLivingEntityDifficulty(LivingEntity m) { + if (m.getCustomName()!=null) { + if (m.getCustomName().contains("Dangerous")) { + return LivingEntityDifficulty.DANGEROUS; + } else + if (m.getCustomName().contains("Deadly")) { + return LivingEntityDifficulty.DEADLY; + } else + if (m.getCustomName().contains("Hellfire")) { + return LivingEntityDifficulty.HELLFIRE; + } else + if (m.getCustomName().contains("Elite")) { + return LivingEntityDifficulty.ELITE; + } else + if (m.getCustomName().contains("End ")) { + return LivingEntityDifficulty.END; + } else + { + return null; + } + } else { + return null; + } + } + @Deprecated public static MonsterDifficulty getMonsterDifficulty(Monster m) { /*if (m.getCustomName()!=null) { @@ -908,7 +934,7 @@ public class MonsterController { } } - public static void SetupCustomName(String prefix, LivingEntity m) { + public static void SetupCustomName(LivingEntityDifficulty diff, LivingEntity m) { String MonsterName = m.getType().toString().toLowerCase(); if (m.getType()==EntityType.SKELETON) { Skeleton ss = (Skeleton)m; @@ -924,7 +950,7 @@ public class MonsterController { } //m.setCustomName(prefix.equalsIgnoreCase("")?"":(prefix+" ")+GenericFunctions.CapitalizeFirstLetters(MonsterName.replaceAll("_", " ")+(isZombieLeader(m)?" Leader":""))); LivingEntityStructure les = LivingEntityStructure.GetLivingEntityStructure(m); - les.difficulty_modifier = prefix; + les.difficulty_modifier = diff.getDifficultyString(); les.suffix = (isZombieLeader(m)?"Leader":""); } @@ -937,7 +963,7 @@ public class MonsterController { } else { m.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE,Integer.MAX_VALUE,1)); } - SetupCustomName(ChatColor.DARK_AQUA+"Dangerous",m); + SetupCustomName(led,m); if(isZombieLeader(m)) { TwosideKeeper.log(" Converting "+GenericFunctions.GetEntityDisplayName(m)+" to Leader.",TwosideKeeper.SPAWN_DEBUG_LEVEL); @@ -966,7 +992,7 @@ public class MonsterController { } else { m.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE,Integer.MAX_VALUE,4)); } - SetupCustomName(ChatColor.GOLD+"Deadly",m); + SetupCustomName(led,m); if(isZombieLeader(m)) { TwosideKeeper.log(" Converting "+GenericFunctions.GetEntityDisplayName(m)+" to Leader.",TwosideKeeper.SPAWN_DEBUG_LEVEL); @@ -1000,7 +1026,7 @@ public class MonsterController { } m.addPotionEffect(new PotionEffect(PotionEffectType.FIRE_RESISTANCE,Integer.MAX_VALUE,1)); if (Math.random()<=0.2) {m.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION,Integer.MAX_VALUE,1));} - SetupCustomName(ChatColor.DARK_RED+"Hellfire",m); + SetupCustomName(led,m); if(isZombieLeader(m)) { TwosideKeeper.log(" Converting "+GenericFunctions.GetEntityDisplayName(m)+" to Leader.",TwosideKeeper.SPAWN_DEBUG_LEVEL); @@ -1022,7 +1048,7 @@ public class MonsterController { m.getAttribute(Attribute.GENERIC_FOLLOW_RANGE).setBaseValue(64.0); }break; case ELITE:{ - SetupCustomName(ChatColor.DARK_PURPLE+"Elite",m); + SetupCustomName(led,m); //m.setCustomName(ChatColor.DARK_AQUA+"Dangerous Mob"); //m.setCustomNameVisible(true); m.setMaxHealth(48000); @@ -1051,7 +1077,7 @@ public class MonsterController { } else { m.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE,Integer.MAX_VALUE,0)); } - SetupCustomName("",m); + SetupCustomName(led,m); if(isZombieLeader(m)) { m.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE,Integer.MAX_VALUE,8)); @@ -1080,7 +1106,7 @@ public class MonsterController { } m.addPotionEffect(new PotionEffect(PotionEffectType.FIRE_RESISTANCE,Integer.MAX_VALUE,1)); m.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION,Integer.MAX_VALUE,3)); - SetupCustomName(ChatColor.DARK_BLUE+""+ChatColor.MAGIC+"End",m); + SetupCustomName(led,m); if(isZombieLeader(m)) { m.setMaxHealth(32000); //Target is 1600 HP. @@ -1105,7 +1131,8 @@ public class MonsterController { */ @Deprecated public static Monster convertMonster(Monster m, MonsterDifficulty md) { - switch (md) { + LivingEntityDifficulty led = md.getLivingEntityDifficultyEquivalent(); + switch (led) { case DANGEROUS: { if (isAllowedToEquipItems(m)) { m.getEquipment().clear(); @@ -1113,7 +1140,7 @@ public class MonsterController { } else { m.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE,Integer.MAX_VALUE,1)); } - SetupCustomName(ChatColor.DARK_AQUA+"Dangerous",m); + SetupCustomName(led,m); if(isZombieLeader(m)) { m.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE,Integer.MAX_VALUE,8)); @@ -1141,7 +1168,7 @@ public class MonsterController { } else { m.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE,Integer.MAX_VALUE,4)); } - SetupCustomName(ChatColor.GOLD+"Deadly",m); + SetupCustomName(led,m); if(isZombieLeader(m)) { m.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE,Integer.MAX_VALUE,8)); @@ -1174,7 +1201,7 @@ public class MonsterController { } m.addPotionEffect(new PotionEffect(PotionEffectType.FIRE_RESISTANCE,Integer.MAX_VALUE,1)); if (Math.random()<=0.2) {m.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION,Integer.MAX_VALUE,1));} - SetupCustomName(ChatColor.DARK_RED+"Hellfire",m); + SetupCustomName(led,m); if(isZombieLeader(m)) { m.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE,Integer.MAX_VALUE,8)); @@ -1195,7 +1222,7 @@ public class MonsterController { m.getAttribute(Attribute.GENERIC_FOLLOW_RANGE).setBaseValue(64.0); }break; case ELITE:{ - SetupCustomName(ChatColor.DARK_PURPLE+"Elite",m); + SetupCustomName(led,m); //m.setCustomName(ChatColor.DARK_AQUA+"Dangerous Mob"); //m.setCustomNameVisible(true); m.setMaxHealth(4800); @@ -1224,7 +1251,7 @@ public class MonsterController { } else { m.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE,Integer.MAX_VALUE,0)); } - SetupCustomName("",m); + SetupCustomName(led,m); if(isZombieLeader(m)) { m.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE,Integer.MAX_VALUE,8)); @@ -1253,7 +1280,7 @@ public class MonsterController { } m.addPotionEffect(new PotionEffect(PotionEffectType.FIRE_RESISTANCE,Integer.MAX_VALUE,1)); m.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION,Integer.MAX_VALUE,3)); - SetupCustomName(ChatColor.DARK_BLUE+""+ChatColor.MAGIC+"End",m); + SetupCustomName(led,m); if(isZombieLeader(m)) { m.setMaxHealth(32000); //Target is 1600 HP. diff --git a/src/sig/plugin/TwosideKeeper/PlayerStructure.java b/src/sig/plugin/TwosideKeeper/PlayerStructure.java index 2ae4b4e..e697f55 100644 --- a/src/sig/plugin/TwosideKeeper/PlayerStructure.java +++ b/src/sig/plugin/TwosideKeeper/PlayerStructure.java @@ -13,6 +13,7 @@ import org.bukkit.Color; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; +import org.bukkit.boss.BossBar; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; @@ -23,6 +24,7 @@ import org.bukkit.inventory.meta.BookMeta; import org.bukkit.potion.PotionEffect; import sig.plugin.TwosideKeeper.HelperStructures.BowMode; +import sig.plugin.TwosideKeeper.HelperStructures.Channel; import sig.plugin.TwosideKeeper.HelperStructures.DeathStructure; import sig.plugin.TwosideKeeper.HelperStructures.FilterCubeItem; import sig.plugin.TwosideKeeper.HelperStructures.PlayerMode; @@ -149,6 +151,7 @@ public class PlayerStructure { public long lastusedearthwave = TwosideKeeper.getServerTickTime(); public long lastusedwindslash = TwosideKeeper.getServerTickTime(); public long lastusedbeastwithin = TwosideKeeper.getServerTickTime(); + public long lastusedunstoppableteam = TwosideKeeper.getServerTickTime(); public long iframetime = 0; @@ -207,6 +210,7 @@ public class PlayerStructure { public long lastCrippleTick=0; public long lastBurnTick=0; public float MoveSpeedMultBeforeCripple=1f; + public Channel currentChannel=null; List equipmentset = new ArrayList(); @@ -266,6 +270,7 @@ public class PlayerStructure { this.lastusedwindslash=(TwosideKeeper.getServerType()==ServerType.MAIN)?TwosideKeeper.getServerTickTime():0; this.icewandused=(TwosideKeeper.getServerType()==ServerType.MAIN)?TwosideKeeper.getServerTickTime():0; this.lastusedbeastwithin=(TwosideKeeper.getServerType()==ServerType.MAIN)?TwosideKeeper.getServerTickTime():0; + this.lastusedunstoppableteam=(TwosideKeeper.getServerType()==ServerType.MAIN)?TwosideKeeper.getServerTickTime():0; this.damagedata = new DamageLogger(p); this.damagelogging=false; this.isPlayingSpleef=false; @@ -448,9 +453,15 @@ public class PlayerStructure { workable.set("BUFF"+(buffcounter)+"_name", b.getDisplayName()); workable.set("BUFF"+(buffcounter)+"_duration", b.getRemainingBuffTime()); workable.set("BUFF"+(buffcounter)+"_amplifier", b.getAmplifier()); - workable.set("BUFF"+(buffcounter)+"_color", b.getBuffParticleColor().asRGB()); + if (b.getBuffParticleColor()!=null) { + workable.set("BUFF"+(buffcounter)+"_color", b.getBuffParticleColor().asRGB()); + } else { + workable.set("BUFF"+(buffcounter)+"_color", "NULL"); + } workable.set("BUFF"+(buffcounter)+"_icon", b.getBuffIcon()); workable.set("BUFF"+(buffcounter)+"_isGoodBuff", b.isGoodBuff()); + workable.set("BUFF"+(buffcounter)+"_canBuffBeRemoved", b.buffCanBeRemoved()); + workable.set("BUFF"+(buffcounter)+"_displayTimerAlways", b.getDisplayTimerAlways()); } //Create a config for the player. @@ -515,6 +526,7 @@ public class PlayerStructure { workable.addDefault("COOLDOWN_lastlifesavertime", lastlifesavertime); workable.addDefault("COOLDOWN_lastusedwindslash", lastusedwindslash); workable.addDefault("COOLDOWN_lastusedbeastwithin", lastusedbeastwithin); + workable.addDefault("COOLDOWN_lastusedunstoppableteam", lastusedunstoppableteam); workable.addDefault("BUFFCOUNT", 0); workable.addDefault("rangermode", "CLOSE"); @@ -574,6 +586,7 @@ public class PlayerStructure { this.lastlifesavertime = workable.getLong("COOLDOWN_lastlifesavertime"); this.lastusedwindslash = workable.getLong("COOLDOWN_lastusedwindslash"); this.lastusedbeastwithin = workable.getLong("COOLDOWN_lastusedbeastwithin"); + this.lastusedunstoppableteam = workable.getLong("COOLDOWN_lastusedunstoppableteam"); this.vacuumsuckup = workable.getBoolean("vacuumsuckup"); this.equipweapons = workable.getBoolean("equipweapons"); this.equiparmor = workable.getBoolean("equiparmor"); @@ -593,14 +606,17 @@ public class PlayerStructure { workable.getString("BUFF"+i+"_icon"), workable.getBoolean("BUFF"+i+"_isGoodBuff") ));*/ - buffs.put(workable.getString("BUFF"+i+"_key"), new Buff( + Buff b = new Buff( workable.getString("BUFF"+i+"_name"), workable.getLong("BUFF"+i+"_duration"), workable.getInt("BUFF"+i+"_amplifier"), - Color.fromRGB(workable.getInt("BUFF"+i+"_color")), + (workable.isColor("BUFF"+i+"_color")?Color.fromRGB(workable.getInt("BUFF"+i+"_color")):null), workable.getString("BUFF"+i+"_icon"), - workable.getBoolean("BUFF"+i+"_isGoodBuff") - )); + workable.getBoolean("BUFF"+i+"_isGoodBuff"), + !workable.getBoolean("BUFF"+i+"_canBuffBeRemoved") + ); + b.setDisplayTimerAlways(workable.getBoolean("BUFF"+i+"_displayTimerAlways")); + buffs.put(workable.getString("BUFF"+i+"_key"), b); } if (this.hasDied) { @@ -620,6 +636,10 @@ public class PlayerStructure { } } + public static void removeTemporaryCooldownDisplayBuffs(Player p) { + Buff.removeBuff(p, "Unstoppable Team Unavailable"); + } + public static PlayerStructure GetPlayerStructure(Player p) { if (TwosideKeeper.playerdata.containsKey(p.getUniqueId())) { return TwosideKeeper.playerdata.get(p.getUniqueId()); diff --git a/src/sig/plugin/TwosideKeeper/TwosideKeeper.java b/src/sig/plugin/TwosideKeeper/TwosideKeeper.java index d3f360e..0a5ed69 100644 --- a/src/sig/plugin/TwosideKeeper/TwosideKeeper.java +++ b/src/sig/plugin/TwosideKeeper/TwosideKeeper.java @@ -186,6 +186,7 @@ import net.minecraft.server.v1_9_R1.EnumParticle; import net.minecraft.server.v1_9_R1.MinecraftServer; import sig.plugin.AutoPluginUpdate.AnnounceUpdateEvent; import sig.plugin.TwosideKeeper.Boss.Arena; +import sig.plugin.TwosideKeeper.Events.EntityChannelCastEvent; import sig.plugin.TwosideKeeper.Events.EntityDamagedEvent; import sig.plugin.TwosideKeeper.Events.InventoryUpdateEvent; import sig.plugin.TwosideKeeper.Events.InventoryUpdateEvent.UpdateReason; @@ -196,6 +197,7 @@ import sig.plugin.TwosideKeeper.HelperStructures.ArtifactItem; import sig.plugin.TwosideKeeper.HelperStructures.ArtifactItemType; import sig.plugin.TwosideKeeper.HelperStructures.BankSession; import sig.plugin.TwosideKeeper.HelperStructures.BowMode; +import sig.plugin.TwosideKeeper.HelperStructures.Channel; import sig.plugin.TwosideKeeper.HelperStructures.CloudRunnable; import sig.plugin.TwosideKeeper.HelperStructures.CubeType; import sig.plugin.TwosideKeeper.HelperStructures.CustomItem; @@ -243,6 +245,7 @@ import sig.plugin.TwosideKeeper.HelperStructures.Utils.InventoryUtils; import sig.plugin.TwosideKeeper.HelperStructures.Utils.ItemCubeUtils; import sig.plugin.TwosideKeeper.HelperStructures.Utils.ItemUtils; import sig.plugin.TwosideKeeper.HelperStructures.Utils.MessageUtils; +import sig.plugin.TwosideKeeper.HelperStructures.Utils.PlayerUtils; import sig.plugin.TwosideKeeper.HelperStructures.Utils.SoundUtils; import sig.plugin.TwosideKeeper.HelperStructures.Utils.TimeUtils; import sig.plugin.TwosideKeeper.HelperStructures.Utils.Classes.SoundData; @@ -436,6 +439,7 @@ public class TwosideKeeper extends JavaPlugin implements Listener { public static final int ICEWAND_COOLDOWN = 1200; public static final int WINDSLASH_COOLDOWN = 100; public static final int BEASTWITHIN_COOLDOWN = 2400; + public static final int UNSTOPPABLETEAM_COOLDOWN = 3000; public static int damagequeue = 0; public static List damagequeuelist = new ArrayList(); @@ -482,6 +486,7 @@ public class TwosideKeeper extends JavaPlugin implements Listener { public static List windslashes = new ArrayList(); public static List blocknodes = new ArrayList(); public static HashMap temporaryblocks = new HashMap(); + public static List channels = new ArrayList(); //public static stats StatCommand = new stats(); @@ -801,6 +806,7 @@ public class TwosideKeeper extends JavaPlugin implements Listener { if (e instanceof Player) { Player p = (Player)e; aPlugin.API.setPlayerSpeedMultiplier(p, 1); + p.setWalkSpeed(0.2f); } GlowAPI.setGlowing(e, null, Bukkit.getOnlinePlayers()); } @@ -863,6 +869,20 @@ public class TwosideKeeper extends JavaPlugin implements Listener { } } TwosideKeeper.HeartbeatLogger.AddEntry("Temporary Block Node Handling", (int)(System.nanoTime()-time));time=System.nanoTime(); + + for (Channel c : channels) { + if (!c.runTick()) { + if (c.getLivingEntity() instanceof Player) { + PlayerStructure pd = PlayerStructure.GetPlayerStructure((Player)c.getLivingEntity()); + pd.currentChannel=null; + } else { + LivingEntityStructure les = LivingEntityStructure.GetLivingEntityStructure(c.getLivingEntity()); + les.currentChannel=null; + } + ScheduleRemoval(channels,c); + } + } + TwosideKeeper.HeartbeatLogger.AddEntry("Temporary Channel Handling", (int)(System.nanoTime()-time));time=System.nanoTime(); if ((int)(System.nanoTime()-totaltime)/1000000d>50) { TwosideKeeper.log("WARNING! Structure Handling took longer than 1 tick! "+((int)(System.nanoTime()-totaltime)/1000000d)+"ms", 0); @@ -1206,7 +1226,7 @@ public class TwosideKeeper extends JavaPlugin implements Listener { //ReplaceBlockTask.CleanupTemporaryBlock(tb); LivingEntityStructure les = livingentitydata.get(id); les.m.setCustomName(les.getUnloadedName()); - TwosideKeeper.log("Saving unloaded monster "+les.getUnloadedName(), 0); + //TwosideKeeper.log("Saving unloaded monster "+les.getUnloadedName(), 0); } log(ChatColor.YELLOW+" "+(System.currentTimeMillis()-betweentime)+"ms",CLEANUP_DEBUG); long endtime = System.currentTimeMillis(); @@ -1933,9 +1953,20 @@ public class TwosideKeeper extends JavaPlugin implements Listener { case "SUPPRESSME":{ GenericFunctions.addSuppressionTime(p, 200); }break; + case "TESTCHANNEL":{ + new Channel(p,"Test Spell",100); + }break; + case "TESTAREACHANNEL":{ + List ents = p.getNearbyEntities(10, 10, 10); + for (Entity ent : ents) { + if (ent instanceof LivingEntity) { + LivingEntity l = (LivingEntity)ent; + new Channel(l,"Test Spell",100); + } + } + }break; } } - //LivingEntity m = MonsterController.convertMonster((Monster)p.getWorld().spawnEntity(p.getLocation(),EntityType.ZOMBIE), MonsterDifficulty.ELITE); /* StackTraceElement[] stacktrace = new Throwable().getStackTrace(); @@ -2683,6 +2714,7 @@ public class TwosideKeeper extends JavaPlugin implements Listener { AnnounceDealOfTheDay(ev.getPlayer()); playerdata.put(ev.getPlayer().getUniqueId(), new PlayerStructure(ev.getPlayer(),getServerTickTime())); PlayerStructure.setDefaultCooldowns(ev.getPlayer()); + PlayerStructure.removeTemporaryCooldownDisplayBuffs(ev.getPlayer()); ItemSet.updateItemSets(ev.getPlayer()); log("[TASK] New Player Data has been added. Size of array: "+playerdata.size(),4); @@ -4438,6 +4470,11 @@ public class TwosideKeeper extends JavaPlugin implements Listener { } return bursted; } + + @EventHandler(priority=EventPriority.LOW,ignoreCancelled = true) + public void onChannelCast(EntityChannelCastEvent ev) { + //TwosideKeeper.log(GenericFunctions.getDisplayName(ev.getLivingEntity())+" has finished casting "+ev.getAbilityName(), 0); + } @EventHandler(priority=EventPriority.LOW,ignoreCancelled = true) public void onBlockPlace(BlockPlaceEvent ev) { @@ -4943,7 +4980,26 @@ public class TwosideKeeper extends JavaPlugin implements Listener { ev.setCancelled(true); return; } + if (PlayerMode.getPlayerMode(p)==PlayerMode.DEFENDER && + ItemSet.hasFullSet(p, ItemSet.PROTECTOR)) { + PlayerStructure pd = PlayerStructure.GetPlayerStructure(p); + if (PlayerUtils.cooldownAvailable(pd.lastusedunstoppableteam, UNSTOPPABLETEAM_COOLDOWN, p)) { + Channel.createNewChannel(p, "Unstoppable Team", 20); + pd.lastusedunstoppableteam=TwosideKeeper.getServerTickTime(); + UpdateUnstoppableTeamBuff(p, pd); + } else { + p.sendTitle("", ChatColor.GOLD+"Unstoppable Team not ready to cast!"); + UpdateUnstoppableTeamBuff(p, pd); + } + ev.setCancelled(true); + return; + } } + private void UpdateUnstoppableTeamBuff(Player p, PlayerStructure pd) { + Buff b = new Buff("Unstoppable Team Unavailable",PlayerUtils.cooldownTimeRemaining(pd.lastusedunstoppableteam, UNSTOPPABLETEAM_COOLDOWN, p),0,null,"",true); + b.setDisplayTimerAlways(true); + Buff.addBuff(p, "Unstoppable Team Unavailable", b); + } @SuppressWarnings("deprecation") @EventHandler(priority=EventPriority.LOW,ignoreCancelled = true) @@ -5281,6 +5337,10 @@ public class TwosideKeeper extends JavaPlugin implements Listener { @EventHandler(priority=EventPriority.LOW,ignoreCancelled = true) public void onItemChange(PlayerItemHeldEvent ev) { final Player player = ev.getPlayer(); + if (GenericFunctions.isSuppressed(player)) { + ev.setCancelled(true); + return; + } Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() { @Override public void run() { @@ -6107,7 +6167,7 @@ public class TwosideKeeper extends JavaPlugin implements Listener { for (Entity e : ev.getChunk().getEntities()) { if (e instanceof LivingEntity) { LivingEntity l = (LivingEntity)e; - if (l.isValid()) { + if (l!=null && l.isValid()) { LivingEntityStructure les = LivingEntityStructure.GetLivingEntityStructure(l); l.setCustomName(les.getUnloadedName()); } @@ -6121,14 +6181,16 @@ public class TwosideKeeper extends JavaPlugin implements Listener { TwosideKeeper.custommonsters.put(m.getUniqueId(), new Dummy(m)); return; } - if (m instanceof Monster) { - MonsterDifficulty md = MonsterController.getMonsterDifficulty((Monster)m); - if (md == MonsterDifficulty.ELITE) { + if (m instanceof LivingEntity) { + //MonsterDifficulty md = MonsterController.getMonsterDifficulty((Monster)m); + LivingEntityDifficulty led = MonsterController.getLivingEntityDifficulty(m); + if (led == LivingEntityDifficulty.ELITE) { ms.SetElite(true); + TwosideKeeperAPI.adjustLivingEntityDifficulty(m, LivingEntityDifficulty.ELITE); } if (MonsterController.isZombieLeader(m)) { - m = MonsterController.convertMonster((Monster)m,md); - log("Setting a monster with Difficulty "+MonsterController.getMonsterDifficulty((Monster)m).name()+" w/"+m.getHealth()+"/"+m.getMaxHealth()+" HP to a Leader.",5); + m = MonsterController.convertLivingEntity((Monster)m,led); + log("Setting a monster with Difficulty "+MonsterController.getLivingEntityDifficulty(m).name()+" w/"+m.getHealth()+"/"+m.getMaxHealth()+" HP to a Leader.",5); ms.SetLeader(true); return; } @@ -6141,7 +6203,8 @@ public class TwosideKeeper extends JavaPlugin implements Listener { Guardian g = (Guardian)m; if (g.isElder()) { ms.SetElite(true); - g.setCustomName(ChatColor.LIGHT_PURPLE+"Elite Guardian"); + //g.setCustomName(ChatColor.LIGHT_PURPLE+"Elite Guardian"); + LivingEntityStructure.setCustomLivingEntityName(m, "Guardian"); g.setCustomNameVisible(true); return; } @@ -6216,13 +6279,16 @@ public class TwosideKeeper extends JavaPlugin implements Listener { if (sk.getSkeletonType()==SkeletonType.WITHER) { if (Math.random()<=0.8) { if (Math.random()<=0.6) { - MonsterController.convertMonster(sk, MonsterDifficulty.HELLFIRE); + //MonsterController.convertMonster(sk, MonsterDifficulty.HELLFIRE); + MonsterController.convertLivingEntity(sk, LivingEntityDifficulty.HELLFIRE); } else { - MonsterController.convertMonster(sk, MonsterDifficulty.DEADLY); + //MonsterController.convertMonster(sk, MonsterDifficulty.DEADLY); + MonsterController.convertLivingEntity(sk, LivingEntityDifficulty.DEADLY); } } else { if (Math.random()<=0.5) { - MonsterController.convertMonster(sk, MonsterDifficulty.DANGEROUS); + //MonsterController.convertMonster(sk, MonsterDifficulty.DANGEROUS); + MonsterController.convertLivingEntity(sk, LivingEntityDifficulty.DANGEROUS); } } } diff --git a/src/sig/plugin/TwosideKeeper/TwosideKeeperAPI.java b/src/sig/plugin/TwosideKeeper/TwosideKeeperAPI.java index a2bb8c4..0b32ed3 100644 --- a/src/sig/plugin/TwosideKeeper/TwosideKeeperAPI.java +++ b/src/sig/plugin/TwosideKeeper/TwosideKeeperAPI.java @@ -17,6 +17,7 @@ import org.bukkit.inventory.ItemStack; import sig.plugin.TwosideKeeper.HelperStructures.ArtifactAbility; import sig.plugin.TwosideKeeper.HelperStructures.ArtifactItem; +import sig.plugin.TwosideKeeper.HelperStructures.Channel; import sig.plugin.TwosideKeeper.HelperStructures.CubeType; import sig.plugin.TwosideKeeper.HelperStructures.ItemSet; import sig.plugin.TwosideKeeper.HelperStructures.LivingEntityDifficulty; @@ -697,4 +698,18 @@ public final class TwosideKeeperAPI { public static boolean buffCanBeRemoved(Buff b) { return Buff.buffCanBeRemoved(b); } + + //Channeling/Spell COMMANDS + public static Channel createNewChannel(LivingEntity l, String spellName, int channelDuration) { + return Channel.createNewChannel(l, spellName, channelDuration); + } + public static boolean isChanneling(LivingEntity l) { + return Channel.isChanneling(l); + } + public static void stopChannel(LivingEntity l) { + Channel.stopChanneling(l); + } + public static Channel getCurrentChannel(LivingEntity l) { + return Channel.getCurrentChannel(l); + } } diff --git a/src/sig/plugin/TwosideKeeper/runServerHeartbeat.java b/src/sig/plugin/TwosideKeeper/runServerHeartbeat.java index d23ea05..e9f2542 100644 --- a/src/sig/plugin/TwosideKeeper/runServerHeartbeat.java +++ b/src/sig/plugin/TwosideKeeper/runServerHeartbeat.java @@ -402,6 +402,7 @@ final class runServerHeartbeat implements Runnable { Bukkit.getScheduler().runTaskLater(TwosideKeeper.plugin, ()->{ if (ent!=null && Buff.hasBuff(ent, "BURN")) { CustomDamage.ApplyDamage(Buff.getBuff(ent, "BURN").getAmplifier(), null, ent, null, "Burn", CustomDamage.IGNOREDODGE|CustomDamage.TRUEDMG|CustomDamage.IGNORE_DAMAGE_TICK); + SoundUtils.playLocalSound((Player)ent, Sound.ENTITY_GENERIC_EXTINGUISH_FIRE, 1.0f, 1.0f); pd.lastBurnTick=TwosideKeeper.getServerTickTime(); } }, (int)(Math.random()*10)); @@ -468,6 +469,7 @@ final class runServerHeartbeat implements Runnable { if (ent!=null && Buff.hasBuff(ent, "BURN")) { CustomDamage.ApplyDamage(Buff.getBuff(ent, "BURN").getAmplifier(), null, ent, null, "Burn", CustomDamage.IGNOREDODGE|CustomDamage.TRUEDMG|CustomDamage.IGNORE_DAMAGE_TICK); les.lastBurnTick=TwosideKeeper.getServerTickTime(); + SoundUtils.playLocalSound((Player)ent, Sound.ENTITY_GENERIC_EXTINGUISH_FIRE, 1.0f, 1.0f); } }, (int)(Math.random()*10)); } @@ -539,7 +541,7 @@ final class runServerHeartbeat implements Runnable { List colors = new ArrayList(); for (String s : pd.buffs.keySet()) { Buff b = pd.buffs.get(s); - if (b.getRemainingBuffTime()>0) { + if (b.getRemainingBuffTime()>0 && b.getBuffParticleColor()!=null) { colors.add(b.getBuffParticleColor()); } } @@ -557,7 +559,7 @@ final class runServerHeartbeat implements Runnable { List colors = new ArrayList(); for (String s : les.buffs.keySet()) { Buff b = les.buffs.get(s); - if (b.getRemainingBuffTime()>0) { + if (b.getRemainingBuffTime()>0 && b.getBuffParticleColor()!=null) { colors.add(b.getBuffParticleColor()); } }