diff --git a/TwosideKeeper.jar b/TwosideKeeper.jar index 9c848b5..73de963 100644 Binary files a/TwosideKeeper.jar and b/TwosideKeeper.jar differ diff --git a/src/sig/plugin/TwosideKeeper/Boss/EliteZombie.java b/src/sig/plugin/TwosideKeeper/Boss/EliteZombie.java new file mode 100644 index 0000000..aa821d2 --- /dev/null +++ b/src/sig/plugin/TwosideKeeper/Boss/EliteZombie.java @@ -0,0 +1,566 @@ +package sig.plugin.TwosideKeeper.Boss; + +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Color; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Particle; +import org.bukkit.Sound; +import org.bukkit.attribute.Attribute; +import org.bukkit.block.Block; +import org.bukkit.boss.BarColor; +import org.bukkit.boss.BarFlag; +import org.bukkit.boss.BarStyle; +import org.bukkit.entity.AreaEffectCloud; +import org.bukkit.entity.Creeper; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Monster; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.potion.PotionData; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.potion.PotionType; +import org.bukkit.util.Vector; +import org.inventivetalent.glow.GlowAPI; + +import sig.plugin.TwosideKeeper.ChargeZombie; +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.Loot; +import sig.plugin.TwosideKeeper.HelperStructures.MonsterDifficulty; +import sig.plugin.TwosideKeeper.HelperStructures.PlayerMode; +import sig.plugin.TwosideKeeper.HelperStructures.Common.GenericFunctions; + +public class EliteZombie extends EliteMonster{ + static int REFRESH_BUFFS = 20*30; + static float FAST_MOVE_SPD = 0.65f; + static long BURST_TIME = 20*3; + static float BURST_LIMIT = 10f; + static int WEAKNESS_DURATION = 20*10; + static int POISON_DURATION = 20*10; + static int LEAP_COOLDOWN = 20*40; + static int ENRAGE_COOLDOWN = 20*60; + static int STORINGENERGY_COOLDOWN = 20*50; + static int WILLPOWER_COOLDOWN = 20*50; + static int GLOW_TIME = 20*1; + + long last_rebuff_time=0; + long last_burstcheck_time=0; + long last_applyglow_time=0; + long last_willpower_increase=0; + double last_leap_time=0; + double last_enrage_time=0; + double last_storingenergy_time=0; + double last_storingenergy_health=0; + double storingenergy_hit=0; + Location target_leap_loc = null; + HashMap storedblocks = new HashMap(); + + public EliteZombie(Monster m) { + super(m); + } + + public void runTick() { + //This monster constantly gives itself its buffs as it may lose some (Debilitation mode). + increaseBarTextScroll(); + dontDrown(); + rebuff(); + regenerateHealth(); + moveFasterToTarget(); + resetToSpawn(); + createBossHealthbar(); + ignoreAllOtherTargets(); + if (m.isValid() && targetlist.size()>0) { + adjustWillpower(); + weakenTeam(); + retargetInAir(); + destroyLiquids(2); + getGlow(); + } + } + + private void createBossHealthbar() { + List currentplayers = bar.getPlayers(); + for (int i=0;iTwosideKeeper.getServerTickTime()) { + for (int i=0;im.getHealth()) { + //Apply a Weakness debuff aura based on how much stronger the team is. + int weaknesslv = Math.min(8,(int)((hp_before_burstcheck-BURST_LIMIT)/BURST_LIMIT)); + createWeaknessCloud(m.getLocation(),weaknesslv); + } + last_burstcheck_time=TwosideKeeper.getServerTickTime(); + hp_before_burstcheck=m.getHealth(); + } + } + + protected void createWeaknessCloud(Location loc, int weaknesslv) { + AreaEffectCloud lp = (AreaEffectCloud)loc.getWorld().spawnEntity(loc, EntityType.AREA_EFFECT_CLOUD); + lp.setColor(Color.BLACK); + lp.setCustomName("WEAK "+weaknesslv+" "+WEAKNESS_DURATION); + lp.setRadius(2f); + lp.setRadiusPerTick(0.5f/20); + lp.setDuration(20*5); + lp.setReapplicationDelay(20); + lp.setBasePotionData(new PotionData(PotionType.POISON)); + lp.setParticle(Particle.SPELL); + loc.getWorld().playSound(loc, Sound.ENTITY_HOSTILE_SPLASH, 1.0f, 1.0f); + } + + private void adjustWillpower() { + //Check for nearby mobs. Each mob increases willpower by 1. + if (Math.random()<=0.3 && !leaping && !storingenergy) { + int mobcount=0; + List monsterlist = CustomDamage.trimNonMonsterEntities(m.getNearbyEntities(10, 10, 10)); + mobcount=monsterlist.size()-1; + TwosideKeeper.log("Detected mob count: "+mobcount, 5); + if (mobcount>0) { + willpower+=mobcount; + last_willpower_increase=TwosideKeeper.getServerTickTime(); + if (!first_willpower_notification && willpower>20) { + for (int i=0;i=100) { + for (int i=0;i0) { + willpower--; + } + } + } + } + + private void destroyLiquids(int radius) { + for (int x=-radius;x<=radius;x++) { + for (int y=-radius;y<=radius;y++) { + for (int z=-radius;z<=radius;z++) { + Block b = m.getLocation().add(0,-0.9,0).getBlock().getRelative(x,y,z); + if (b.isLiquid()) { + b.setType(Material.AIR); + } + } + } + } + } + + private void retargetInAir() { + if (Math.random()<=0.01) { + Player p = ChooseRandomTarget(); + //p.addPotionEffect(new PotionEffect(PotionEffectType.LEVITATION,20*5,-31)); + GenericFunctions.logAndApplyPotionEffectToPlayer(PotionEffectType.JUMP,20*5,-1,p); + GenericFunctions.logAndApplyPotionEffectToPlayer(PotionEffectType.BLINDNESS,20*1,7,p); + if (Math.random()<=0.25) { + m.setTarget(p); + } + p.setFlying(false); + p.setVelocity(new Vector(0,-1,0)); + GenericFunctions.logAndRemovePotionEffectFromPlayer(PotionEffectType.LEVITATION,p); + GenericFunctions.logAndApplyPotionEffectToPlayer(PotionEffectType.CONFUSION,(int)(20*2.25),0,p); + p.playSound(p.getLocation(), Sound.BLOCK_ANVIL_FALL, 0.4f, 0.8f); + p.playSound(p.getLocation(), Sound.ENTITY_MAGMACUBE_SQUISH, 1.0f, 1.0f); + } + } + + private void moveFasterToTarget() { + if (m.isInsideVehicle()) { + m.eject(); + } + LivingEntity l = m.getTarget(); + if (l!=null && l.getWorld().equals(m.getWorld())) { + if (l.isDead()) { + targetlist.remove(l); + if (targetlist.size()>0) { + m.setTarget(ChooseRandomTarget()); + } else { + m.setTarget(null); + resetToSpawn(); + } + } + if (!storingenergy) { + if (storingenergy_hit>0) { + storingenergy_hit/=1.04f; + if (storingenergy_hit<10) { + storingenergy_hit=0; + } + } + if (l.getLocation().distanceSquared(m.getLocation())>4096 && !leaping) { + //Lose the target. + targetlist.remove(l); + if (targetlist.size()>0) { + m.setTarget(ChooseRandomTarget()); + } else { + m.setTarget(null); + resetToSpawn(); + } + } else + if (l.getLocation().distanceSquared(m.getLocation())>100 && !leaping) { + l.getWorld().playSound(l.getLocation(), Sound.ENTITY_CAT_HISS, 1.0f, 1.0f); + chasing=true; + Bukkit.getScheduler().scheduleSyncDelayedTask(TwosideKeeper.plugin, new Runnable() { + public void run() { + m.teleport(l.getLocation().add(Math.random(),Math.random(),Math.random())); + l.addPotionEffect(new PotionEffect(PotionEffectType.SLOW,20*5,7)); + l.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS,20*1,7)); + chasing=false; + } + },20*2); + } else if (l.getLocation().distanceSquared(m.getLocation())>4) { + m.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED).setBaseValue(FAST_MOVE_SPD); + } else { + m.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED).setBaseValue(DEFAULT_MOVE_SPD); + } + } + + if (l.getLocation().getY()>m.getLocation().getY()+1) { + //Jump up to compensate. Move towards the player too. + m.setVelocity((m.getLocation().getDirection()).add(new Vector(0,0.2*(l.getLocation().getY()-m.getLocation().getY()),0))); + } + } else { + targetlist.remove(l); + m.setTarget(null); + } + } + + private void rebuff() { + if (last_rebuff_time+REFRESH_BUFFS<=TwosideKeeper.getServerTickTime()) { + last_rebuff_time=TwosideKeeper.getServerTickTime(); + m.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE,Integer.MAX_VALUE,8),true); + m.addPotionEffect(new PotionEffect(PotionEffectType.FIRE_RESISTANCE,Integer.MAX_VALUE,8),true); + //m.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION,Integer.MAX_VALUE,2),true); + ItemStack helm = new ItemStack(Material.GOLD_AXE); + m.getEquipment().setItemInMainHand(helm); + m.getEquipment().setItemInMainHandDropChance(1.0f); + helm = new ItemStack(Material.GOLD_HELMET); + m.getEquipment().setHelmet(helm); + m.getEquipment().setHelmet(Loot.GenerateMegaPiece(helm.getType(), true, true, 1)); + m.getEquipment().setHelmetDropChance(1.0f); + if (!leaping) { + m.removePotionEffect(PotionEffectType.LEVITATION); + } + if (!enraged) { + if (m.hasPotionEffect(PotionEffectType.INCREASE_DAMAGE)) { + m.removePotionEffect(PotionEffectType.INCREASE_DAMAGE); + } + } + } + } + + //Triggers when this mob is hit. + public void runHitEvent(LivingEntity damager, double dmg) { + bar.setColor(BarColor.RED); + if (!targetlist.contains(damager) && (damager instanceof Player)) { + targetlist.add((Player)damager); + } + if (!participantlist.contains(damager) && (damager instanceof Player)) { + participantlist.add((Player)damager); + } + if (damager instanceof Player) { + Player p = (Player)damager; + double currentdps=0; + if (dpslist.containsKey(p.getName())) { + currentdps = dpslist.get(p.getName()); + } + dpslist.put(p.getName(), currentdps+dmg); + if ((!p.hasPotionEffect(PotionEffectType.WEAKNESS) || GenericFunctions.getPotionEffectLevel(PotionEffectType.WEAKNESS, p)<9) && + !PlayerMode.isRanger(p)) { + GenericFunctions.logAndApplyPotionEffectToPlayer(PotionEffectType.WEAKNESS,35,9,p,true); + } + } + last_regen_time=TwosideKeeper.getServerTickTime(); + double randomrate = 0d; + if (!chasing && CustomDamage.getPercentHealthRemaining(m)<=50) { + if (last_leap_time+LEAP_COOLDOWN<=TwosideKeeper.getServerTickTime()) { + performLeap(); + } + } + if (CustomDamage.getPercentHealthRemaining(m)<=25) { + if (!leaping && !chasing && + last_storingenergy_time+STORINGENERGY_COOLDOWN<=TwosideKeeper.getServerTickTime()) { + last_storingenergy_time=TwosideKeeper.getServerTickTime(); + storingenergy=true; + for (int i=0;i0) { + storingenergy_hit=(last_storingenergy_health-m.getHealth())*500d; + for (int i=0;i50) { + randomrate = 1/16d; + } else + if (CustomDamage.getPercentHealthRemaining(m)<=50 && + CustomDamage.getPercentHealthRemaining(m)>25) { + randomrate = 1/8d; + } else + { + randomrate = 1/4d; + } + if (Math.random()<=randomrate) { + EntityType choice = null; + switch ((int)(Math.random()*4)) { + case 0 :{ + choice = EntityType.ZOMBIE; + }break; + case 1 :{ + choice = EntityType.SKELETON; + }break; + case 2 :{ + choice = EntityType.CREEPER; + }break; + case 3 :{ + choice = EntityType.ENDERMAN; + }break; + default:{ + choice = EntityType.ZOMBIE; + } + } + 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); + } + if (CustomDamage.getPercentHealthRemaining(m)<10) { + Player target = targetlist.get((int)(Math.random() * targetlist.size())); + Creeper nm = (Creeper)m.getWorld().spawnEntity(target.getLocation().add(0,30,0),EntityType.CREEPER); + if (Math.random()<=0.5) { + nm.setPowered(true); + } + nm.setTarget(target); + MonsterController.convertMonster(nm, MonsterDifficulty.HELLFIRE); + } + } + + @SuppressWarnings("deprecation") + private void performLeap() { + last_leap_time = TwosideKeeper.getServerTickTime(); + int radius = (int)(6*(CustomDamage.getPercentHealthMissing(m)/100d))+1; + //Choose a target randomly. + Player target = ChooseRandomTarget(); + m.setTarget(target); + Bukkit.getScheduler().scheduleSyncDelayedTask(TwosideKeeper.plugin, new Runnable() { + public void run() { + m.addPotionEffect(new PotionEffect(PotionEffectType.LEVITATION,Integer.MAX_VALUE,60)); + } + },8); + target_leap_loc = target.getLocation().clone(); + m.addPotionEffect(new PotionEffect(PotionEffectType.LEVITATION,Integer.MAX_VALUE,20)); + for (int x=-radius;x nearbyplayers = GenericFunctions.getNearbyPlayers(target_leap_loc, radius); + for (int i=0;i0) { + nearbyplayers.get(i).setVelocity(new Vector(0,2,0)); + } + } + //GenericFunctions.DealDamageToNearbyPlayers(target_leap_loc, 5*200, radius, true, 2, m, "Leap",false); + //GenericFunctions.getNear + } + },(int)(((20*3)*(CustomDamage.getPercentHealthRemaining(m)/100d))+30)); + } + + //Triggers when this mob hits something. + public void hitEvent(LivingEntity ent) { + if (!targetlist.contains(ent) && (ent instanceof Player)) { + targetlist.add((Player)ent); + } + if (Math.random()<=0.33) { + if (ent.hasPotionEffect(PotionEffectType.POISON)) { + int poisonlv = GenericFunctions.getPotionEffectLevel(PotionEffectType.POISON, ent); + ent.addPotionEffect(new PotionEffect(PotionEffectType.POISON,POISON_DURATION,poisonlv+1),true); + ent.addPotionEffect(new PotionEffect(PotionEffectType.SLOW_DIGGING,POISON_DURATION,poisonlv+1)); + } else { + ent.addPotionEffect(new PotionEffect(PotionEffectType.POISON,POISON_DURATION,0)); + ent.addPotionEffect(new PotionEffect(PotionEffectType.SLOW_DIGGING,POISON_DURATION,0)); + } + } + if (ent instanceof Player) { + Player p = (Player)ent; + if (storingenergy_hit>0) { + p.playSound(p.getLocation(), Sound.ENTITY_ZOMBIE_BREAK_DOOR_WOOD, 1.0f, 1.0f); + GenericFunctions.logAndApplyPotionEffectToPlayer(PotionEffectType.CONFUSION,20*4,0,p); + TwosideKeeper.log("Got hit for "+storingenergy_hit+" damage!", 2); + GenericFunctions.removeNoDamageTick(p, m); + if (CustomDamage.ApplyDamage(storingenergy_hit, m, p, null, "Stored Energy", CustomDamage.IGNOREDODGE)) { + //TwosideKeeperAPI.DealDamageToEntity(.CalculateDamageReduction(storingenergy_hit,p,m),p,m); + storingenergy_hit=0; + } + } + } + } +} diff --git a/src/sig/plugin/TwosideKeeper/Boss/MegaWither.java b/src/sig/plugin/TwosideKeeper/Boss/MegaWither.java new file mode 100644 index 0000000..a936470 --- /dev/null +++ b/src/sig/plugin/TwosideKeeper/Boss/MegaWither.java @@ -0,0 +1,20 @@ +package sig.plugin.TwosideKeeper.Boss; + +import org.bukkit.entity.Monster; + +import sig.plugin.TwosideKeeper.EliteMonster; + +public class MegaWither extends EliteMonster{ + + public MegaWither(Monster m) { + super(m); + } + + public void runTick() { + increaseBarTextScroll(); + regenerateHealth(); + resetToSpawn(); + ignoreAllOtherTargets(); + } + +} diff --git a/src/sig/plugin/TwosideKeeper/CustomDamage.java b/src/sig/plugin/TwosideKeeper/CustomDamage.java index 230b09e..d22a620 100644 --- a/src/sig/plugin/TwosideKeeper/CustomDamage.java +++ b/src/sig/plugin/TwosideKeeper/CustomDamage.java @@ -205,7 +205,7 @@ public class CustomDamage { double armorpendmg = addToPlayerLogger(damager,target,"Armor Pen",calculateArmorPen(damager,dmg,weapon)); addToLoggerActual(damager,dmg); addToPlayerRawDamage(dmg,target); - dmg = CalculateDamageReduction(dmg-armorpendmg,target,damager); + if (!isFlagSet(flags, TRUEDMG)) {dmg = CalculateDamageReduction(dmg-armorpendmg,target,damager);} TwosideKeeper.log("Damage: "+dmg+", Armor Pen Damage: "+armorpendmg, 3); setupDamagePropertiesForPlayer(damager,((crit)?IS_CRIT:0)|((headshot)?IS_HEADSHOT:0)|((preemptive)?IS_PREEMPTIVE:0)); dmg = hardCapDamage(dmg+armorpendmg); @@ -340,7 +340,7 @@ public class CustomDamage { } } if (getDamagerEntity(damager) instanceof LivingEntity) { - LivingEntity m = (Monster)getDamagerEntity(damager); + LivingEntity m = getDamagerEntity(damager); LivingEntityStructure md = LivingEntityStructure.getLivingEntityStructure(m); md.SetTarget(target); } @@ -560,7 +560,7 @@ public class CustomDamage { } } if (!exists) { - TwosideKeeper.elitemonsters.add(new EliteMonster((Monster)target)); + TwosideKeeper.elitemonsters.add(GenericFunctions.getProperEliteMonster((Monster)target)); } } } @@ -601,7 +601,7 @@ public class CustomDamage { } } if (!exists) { - TwosideKeeper.elitemonsters.add(new EliteMonster((Monster)target)); + TwosideKeeper.elitemonsters.add(GenericFunctions.getProperEliteMonster((Monster)target)); } } } @@ -2046,7 +2046,7 @@ public class CustomDamage { } //Returns between 0-100. - static double getPercentHealthRemaining(LivingEntity target) { + public static double getPercentHealthRemaining(LivingEntity target) { return ((target.getHealth()/target.getMaxHealth())*100); } public static double getPercentHealthMissing(LivingEntity target) { diff --git a/src/sig/plugin/TwosideKeeper/DeathManager.java b/src/sig/plugin/TwosideKeeper/DeathManager.java index bdab361..b67a8cd 100644 --- a/src/sig/plugin/TwosideKeeper/DeathManager.java +++ b/src/sig/plugin/TwosideKeeper/DeathManager.java @@ -42,7 +42,7 @@ public class DeathManager { p.teleport(loc); }},1); PlayerStructure pd = PlayerStructure.GetPlayerStructure(p); - pd.deathloot.clear(); + //pd.deathloot.clear(); pd.hasDied=false; p.setCollidable(true); } diff --git a/src/sig/plugin/TwosideKeeper/EliteMonster.java b/src/sig/plugin/TwosideKeeper/EliteMonster.java index 9d70789..edce96f 100644 --- a/src/sig/plugin/TwosideKeeper/EliteMonster.java +++ b/src/sig/plugin/TwosideKeeper/EliteMonster.java @@ -40,56 +40,34 @@ import sig.plugin.TwosideKeeper.HelperStructures.PlayerMode; import sig.plugin.TwosideKeeper.HelperStructures.Common.GenericFunctions; public class EliteMonster { - static int REFRESH_BUFFS = 20*30; - static int RESTORE_HEALTH = 20*10; - static float DEFAULT_MOVE_SPD = 0.3f; - static float FAST_MOVE_SPD = 0.65f; - static long BURST_TIME = 20*3; - static float BURST_LIMIT = 10f; - static int WEAKNESS_DURATION = 20*10; - static int POISON_DURATION = 20*10; - static int LEAP_COOLDOWN = 20*40; - static int ENRAGE_COOLDOWN = 20*60; - static int STORINGENERGY_COOLDOWN = 20*50; - static int WILLPOWER_COOLDOWN = 20*50; + protected static float DEFAULT_MOVE_SPD = 0.3f; static int IGNORE_TARGET_DURATION = 20*20; - static int GLOW_TIME = 20*1; + static int RESTORE_HEALTH = 20*10; static int WAIT_TIME = 20*10; - Monster m; - long last_rebuff_time=0; - long last_regen_time=0; - long last_burstcheck_time=0; - long last_applyglow_time=0; - long last_willpower_increase=0; - double hp_before_burstcheck=0; - double last_leap_time=0; - double last_enrage_time=0; - double last_storingenergy_time=0; - double last_storingenergy_health=0; - double last_ignoretarget_time=0; - double storingenergy_hit=0; - boolean leaping=false; - boolean chasing=false; - boolean enraged=false; - boolean storingenergy=false; - Location target_leap_loc = null; + protected Monster m; Location myspawn = null; - HashMap storedblocks = new HashMap(); - BossBar bar = null; - BossBar willpower_bar = null; - boolean first_willpower_notification=false; + protected BossBar bar = null; + protected BossBar willpower_bar = null; + protected boolean first_willpower_notification=false; int scroll=0; - int willpower=0; - String arrow = "->"; - Player my_only_target=null; + protected int willpower=0; + protected String arrow = "->"; + public Player my_only_target=null; + protected double hp_before_burstcheck=0; + protected long last_regen_time=0; + public double last_ignoretarget_time=0; + protected boolean leaping=false; + protected boolean chasing=false; + protected boolean enraged=false; + protected boolean storingenergy=false; - List targetlist = new ArrayList(); - List participantlist = new ArrayList(); - HashMap dpslist = new HashMap(); + protected List targetlist = new ArrayList(); + protected List participantlist = new ArrayList(); + protected HashMap dpslist = new HashMap(); //Contains all functionality specific to Elite Monsters. //These are checked every 5 ticks, so have very high control over the monster itself. - EliteMonster(Monster m) { + public EliteMonster(Monster m) { this.m=m; m.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED).setBaseValue(DEFAULT_MOVE_SPD); this.hp_before_burstcheck=m.getHealth(); @@ -102,22 +80,18 @@ public class EliteMonster { //This monster constantly gives itself its buffs as it may lose some (Debilitation mode). increaseBarTextScroll(); dontDrown(); - rebuff(); regenerateHealth(); - moveFasterToTarget(); resetToSpawn(); - //createBossHealthbar(); + createBossHealthbar(); ignoreAllOtherTargets(); if (m.isValid() && targetlist.size()>0) { - adjustWillpower(); - weakenTeam(); retargetInAir(); destroyLiquids(2); getGlow(); } } - private void ignoreAllOtherTargets() { + protected void ignoreAllOtherTargets() { if (my_only_target!=null && targetlist.contains(my_only_target)) { m.setTarget(my_only_target); TwosideKeeper.log("I aim at "+m.getTarget()+"!!", 2); @@ -128,7 +102,7 @@ public class EliteMonster { } } - private void increaseBarTextScroll() { + protected void increaseBarTextScroll() { scroll++; switch (scroll%22) { case 11:{ @@ -146,87 +120,6 @@ public class EliteMonster { } } - private void adjustWillpower() { - //Check for nearby mobs. Each mob increases willpower by 1. - if (Math.random()<=0.3 && !leaping && !storingenergy) { - int mobcount=0; - List monsterlist = CustomDamage.trimNonMonsterEntities(m.getNearbyEntities(10, 10, 10)); - mobcount=monsterlist.size()-1; - TwosideKeeper.log("Detected mob count: "+mobcount, 5); - if (mobcount>0) { - willpower+=mobcount; - last_willpower_increase=TwosideKeeper.getServerTickTime(); - if (!first_willpower_notification && willpower>20) { - for (int i=0;i=100) { - for (int i=0;i0) { - willpower--; - } - } - } - } - private void createBossHealthbar() { List currentplayers = bar.getPlayers(); for (int i=0;iTwosideKeeper.getServerTickTime()) { - for (int i=0;i81) { while (myspawn.getBlock().getRelative(0, -1, 0).getType()==Material.AIR && myspawn.getY()>1) { myspawn = myspawn.add(0,-1,0); @@ -282,7 +164,7 @@ public class EliteMonster { } } - private void dontDrown() { + protected void dontDrown() { m.setRemainingAir(m.getMaximumAir()); } @@ -333,121 +215,12 @@ public class EliteMonster { } } - private void weakenTeam() { - if (last_burstcheck_time+BURST_TIME<=TwosideKeeper.getServerTickTime()) { - if (hp_before_burstcheck-BURST_LIMIT>m.getHealth()) { - //Apply a Weakness debuff aura based on how much stronger the team is. - int weaknesslv = Math.min(8,(int)((hp_before_burstcheck-BURST_LIMIT)/BURST_LIMIT)); - createWeaknessCloud(m.getLocation(),weaknesslv); - } - last_burstcheck_time=TwosideKeeper.getServerTickTime(); - hp_before_burstcheck=m.getHealth(); - } - } - - private void createWeaknessCloud(Location loc, int weaknesslv) { - AreaEffectCloud lp = (AreaEffectCloud)loc.getWorld().spawnEntity(loc, EntityType.AREA_EFFECT_CLOUD); - lp.setColor(Color.BLACK); - lp.setCustomName("WEAK "+weaknesslv+" "+WEAKNESS_DURATION); - lp.setRadius(2f); - lp.setRadiusPerTick(0.5f/20); - lp.setDuration(20*5); - lp.setReapplicationDelay(20); - lp.setBasePotionData(new PotionData(PotionType.POISON)); - lp.setParticle(Particle.SPELL); - loc.getWorld().playSound(loc, Sound.ENTITY_HOSTILE_SPLASH, 1.0f, 1.0f); - } - - private void regenerateHealth() { + protected void regenerateHealth() { if (m.getHealth()0) { - m.setTarget(ChooseRandomTarget()); - } else { - m.setTarget(null); - resetToSpawn(); - } - } - if (!storingenergy) { - if (storingenergy_hit>0) { - storingenergy_hit/=1.04f; - if (storingenergy_hit<10) { - storingenergy_hit=0; - } - } - if (l.getLocation().distanceSquared(m.getLocation())>4096 && !leaping) { - //Lose the target. - targetlist.remove(l); - if (targetlist.size()>0) { - m.setTarget(ChooseRandomTarget()); - } else { - m.setTarget(null); - resetToSpawn(); - } - } else - if (l.getLocation().distanceSquared(m.getLocation())>100 && !leaping) { - l.getWorld().playSound(l.getLocation(), Sound.ENTITY_CAT_HISS, 1.0f, 1.0f); - chasing=true; - Bukkit.getScheduler().scheduleSyncDelayedTask(TwosideKeeper.plugin, new Runnable() { - public void run() { - m.teleport(l.getLocation().add(Math.random(),Math.random(),Math.random())); - l.addPotionEffect(new PotionEffect(PotionEffectType.SLOW,20*5,7)); - l.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS,20*1,7)); - chasing=false; - } - },20*2); - } else if (l.getLocation().distanceSquared(m.getLocation())>4) { - m.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED).setBaseValue(FAST_MOVE_SPD); - } else { - m.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED).setBaseValue(DEFAULT_MOVE_SPD); - } - } - - if (l.getLocation().getY()>m.getLocation().getY()+1) { - //Jump up to compensate. Move towards the player too. - m.setVelocity((m.getLocation().getDirection()).add(new Vector(0,0.2*(l.getLocation().getY()-m.getLocation().getY()),0))); - } - } else { - targetlist.remove(l); - m.setTarget(null); - } - } - - private void rebuff() { - if (last_rebuff_time+REFRESH_BUFFS<=TwosideKeeper.getServerTickTime()) { - last_rebuff_time=TwosideKeeper.getServerTickTime(); - m.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE,Integer.MAX_VALUE,8),true); - m.addPotionEffect(new PotionEffect(PotionEffectType.FIRE_RESISTANCE,Integer.MAX_VALUE,8),true); - //m.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION,Integer.MAX_VALUE,2),true); - ItemStack helm = new ItemStack(Material.GOLD_AXE); - m.getEquipment().setItemInMainHand(helm); - m.getEquipment().setItemInMainHandDropChance(1.0f); - helm = new ItemStack(Material.GOLD_HELMET); - m.getEquipment().setHelmet(helm); - m.getEquipment().setHelmet(Loot.GenerateMegaPiece(helm.getType(), true, true, 1)); - m.getEquipment().setHelmetDropChance(1.0f); - if (!leaping) { - m.removePotionEffect(PotionEffectType.LEVITATION); - } - if (!enraged) { - if (m.hasPotionEffect(PotionEffectType.INCREASE_DAMAGE)) { - m.removePotionEffect(PotionEffectType.INCREASE_DAMAGE); - } - } - } - } public void runPlayerLeaveEvent(Player p) { targetlist.remove(p); @@ -471,197 +244,11 @@ public class EliteMonster { currentdps = dpslist.get(p.getName()); } dpslist.put(p.getName(), currentdps+dmg); - if ((!p.hasPotionEffect(PotionEffectType.WEAKNESS) || GenericFunctions.getPotionEffectLevel(PotionEffectType.WEAKNESS, p)<9) && - !PlayerMode.isRanger(p)) { - GenericFunctions.logAndApplyPotionEffectToPlayer(PotionEffectType.WEAKNESS,35,9,p,true); - } } last_regen_time=TwosideKeeper.getServerTickTime(); - double randomrate = 0d; - if (!chasing && CustomDamage.getPercentHealthRemaining(m)<=50) { - if (last_leap_time+LEAP_COOLDOWN<=TwosideKeeper.getServerTickTime()) { - performLeap(); - } - } - if (CustomDamage.getPercentHealthRemaining(m)<=25) { - if (!leaping && !chasing && - last_storingenergy_time+STORINGENERGY_COOLDOWN<=TwosideKeeper.getServerTickTime()) { - last_storingenergy_time=TwosideKeeper.getServerTickTime(); - storingenergy=true; - for (int i=0;i0) { - storingenergy_hit=(last_storingenergy_health-m.getHealth())*500d; - for (int i=0;i50) { - randomrate = 1/16d; - } else - if (CustomDamage.getPercentHealthRemaining(m)<=50 && - CustomDamage.getPercentHealthRemaining(m)>25) { - randomrate = 1/8d; - } else - { - randomrate = 1/4d; - } - if (Math.random()<=randomrate) { - EntityType choice = null; - switch ((int)(Math.random()*4)) { - case 0 :{ - choice = EntityType.ZOMBIE; - }break; - case 1 :{ - choice = EntityType.SKELETON; - }break; - case 2 :{ - choice = EntityType.CREEPER; - }break; - case 3 :{ - choice = EntityType.ENDERMAN; - }break; - default:{ - choice = EntityType.ZOMBIE; - } - } - 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); - } - if (CustomDamage.getPercentHealthRemaining(m)<10) { - Player target = targetlist.get((int)(Math.random() * targetlist.size())); - Creeper nm = (Creeper)m.getWorld().spawnEntity(target.getLocation().add(0,30,0),EntityType.CREEPER); - if (Math.random()<=0.5) { - nm.setPowered(true); - } - nm.setTarget(target); - MonsterController.convertMonster(nm, MonsterDifficulty.HELLFIRE); - } - } - - @SuppressWarnings("deprecation") - private void performLeap() { - last_leap_time = TwosideKeeper.getServerTickTime(); - int radius = (int)(6*(CustomDamage.getPercentHealthMissing(m)/100d))+1; - //Choose a target randomly. - Player target = ChooseRandomTarget(); - m.setTarget(target); - Bukkit.getScheduler().scheduleSyncDelayedTask(TwosideKeeper.plugin, new Runnable() { - public void run() { - m.addPotionEffect(new PotionEffect(PotionEffectType.LEVITATION,Integer.MAX_VALUE,60)); - } - },8); - target_leap_loc = target.getLocation().clone(); - m.addPotionEffect(new PotionEffect(PotionEffectType.LEVITATION,Integer.MAX_VALUE,20)); - for (int x=-radius;x nearbyplayers = GenericFunctions.getNearbyPlayers(target_leap_loc, radius); - for (int i=0;i0) { - nearbyplayers.get(i).setVelocity(new Vector(0,2,0)); - } - } - //GenericFunctions.DealDamageToNearbyPlayers(target_leap_loc, 5*200, radius, true, 2, m, "Leap",false); - //GenericFunctions.getNear - } - },(int)(((20*3)*(CustomDamage.getPercentHealthRemaining(m)/100d))+30)); } - private Player ChooseRandomTarget() { - if (targetlist.size()>0) { - Player p = targetlist.get((int)(Math.random() * targetlist.size())); - GenericFunctions.logAndApplyPotionEffectToPlayer(PotionEffectType.BLINDNESS,20*1,7,p); - m.setTarget(p); - TwosideKeeper.log("Set new target to "+p.getName(), 2); - return p; - } else { - return null; - } - } - - private Location getNearbyFreeLocation(Location l) { + protected Location getNearbyFreeLocation(Location l) { return getNearbyFreeLocation(l,3); } @@ -683,28 +270,17 @@ public class EliteMonster { if (!targetlist.contains(ent) && (ent instanceof Player)) { targetlist.add((Player)ent); } - if (Math.random()<=0.33) { - if (ent.hasPotionEffect(PotionEffectType.POISON)) { - int poisonlv = GenericFunctions.getPotionEffectLevel(PotionEffectType.POISON, ent); - ent.addPotionEffect(new PotionEffect(PotionEffectType.POISON,POISON_DURATION,poisonlv+1),true); - ent.addPotionEffect(new PotionEffect(PotionEffectType.SLOW_DIGGING,POISON_DURATION,poisonlv+1)); - } else { - ent.addPotionEffect(new PotionEffect(PotionEffectType.POISON,POISON_DURATION,0)); - ent.addPotionEffect(new PotionEffect(PotionEffectType.SLOW_DIGGING,POISON_DURATION,0)); - } - } - if (ent instanceof Player) { - Player p = (Player)ent; - if (storingenergy_hit>0) { - p.playSound(p.getLocation(), Sound.ENTITY_ZOMBIE_BREAK_DOOR_WOOD, 1.0f, 1.0f); - GenericFunctions.logAndApplyPotionEffectToPlayer(PotionEffectType.CONFUSION,20*4,0,p); - TwosideKeeper.log("Got hit for "+storingenergy_hit+" damage!", 2); - GenericFunctions.removeNoDamageTick(p, m); - if (CustomDamage.ApplyDamage(storingenergy_hit, m, p, null, "Stored Energy", CustomDamage.IGNOREDODGE)) { - //TwosideKeeperAPI.DealDamageToEntity(.CalculateDamageReduction(storingenergy_hit,p,m),p,m); - storingenergy_hit=0; - } - } + } + + public Player ChooseRandomTarget() { + if (targetlist.size()>0) { + Player p = targetlist.get((int)(Math.random() * targetlist.size())); + GenericFunctions.logAndApplyPotionEffectToPlayer(PotionEffectType.BLINDNESS,20*1,7,p); + m.setTarget(p); + TwosideKeeper.log("Set new target to "+p.getName(), 2); + return p; + } else { + return null; } } diff --git a/src/sig/plugin/TwosideKeeper/HelperStructures/Common/GenericFunctions.java b/src/sig/plugin/TwosideKeeper/HelperStructures/Common/GenericFunctions.java index 7dc08da..4c8b362 100644 --- a/src/sig/plugin/TwosideKeeper/HelperStructures/Common/GenericFunctions.java +++ b/src/sig/plugin/TwosideKeeper/HelperStructures/Common/GenericFunctions.java @@ -29,6 +29,8 @@ import org.bukkit.entity.Projectile; import org.bukkit.entity.Skeleton; import org.bukkit.entity.Skeleton.SkeletonType; import org.bukkit.entity.Spider; +import org.bukkit.entity.Wither; +import org.bukkit.entity.Zombie; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; @@ -58,6 +60,8 @@ import sig.plugin.TwosideKeeper.LivingEntityStructure; import sig.plugin.TwosideKeeper.PlayerStructure; import sig.plugin.TwosideKeeper.TwosideKeeper; import sig.plugin.TwosideKeeper.TwosideKeeperAPI; +import sig.plugin.TwosideKeeper.Boss.EliteZombie; +import sig.plugin.TwosideKeeper.Boss.MegaWither; import sig.plugin.TwosideKeeper.HelperStructures.ArtifactAbility; import sig.plugin.TwosideKeeper.HelperStructures.BowMode; import sig.plugin.TwosideKeeper.HelperStructures.EliteMonsterLocationFinder; @@ -3186,15 +3190,19 @@ public class GenericFunctions { } } - private static ItemStack AddCustomPotionTag(ItemStack item) { - List lore = item.getItemMeta().getLore(); - PotionMeta pm = (PotionMeta)item.getItemMeta(); - for (PotionEffect pe : pm.getCustomEffects()) { - lore.add(0,ChatColor.GRAY+UserFriendlyPotionEffectTypeName(pe.getType())+" "+WorldShop.toRomanNumeral(pe.getAmplifier()+1)+" ("+WorldShop.toReadableDuration(pe.getDuration())+")"); - } - pm.setLore(lore); - pm.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS); - item.setItemMeta(pm); + public static ItemStack AddCustomPotionTag(ItemStack item) { + if (item!=null && + item.hasItemMeta() && + item.getItemMeta() instanceof PotionMeta) { + List lore = item.getItemMeta().getLore(); + PotionMeta pm = (PotionMeta)item.getItemMeta(); + for (PotionEffect pe : pm.getCustomEffects()) { + lore.add(0,ChatColor.GRAY+UserFriendlyPotionEffectTypeName(pe.getType())+" "+WorldShop.toRomanNumeral(pe.getAmplifier()+1)+" ("+WorldShop.toReadableDuration(pe.getDuration())+")"); + } + pm.setLore(lore); + pm.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS); + item.setItemMeta(pm); + } return item; } @@ -4248,4 +4256,15 @@ public class GenericFunctions { } from.clear(); } + + public static EliteMonster getProperEliteMonster(Monster target) { + if (target instanceof Zombie) { + return new EliteZombie(target); + } + if (target instanceof Wither) { + return new MegaWither(target); + } + TwosideKeeper.log("Elite Monster for monster "+target.getName()+" UNDEFINED. Defaulting to EliteZombie type.", 0); + return new EliteZombie(target); + } } diff --git a/src/sig/plugin/TwosideKeeper/HelperStructures/ItemSet.java b/src/sig/plugin/TwosideKeeper/HelperStructures/ItemSet.java index e5ffb6d..6c89a3c 100644 --- a/src/sig/plugin/TwosideKeeper/HelperStructures/ItemSet.java +++ b/src/sig/plugin/TwosideKeeper/HelperStructures/ItemSet.java @@ -22,7 +22,7 @@ public enum ItemSet { DARNYS(1,1, 10,5, 20,5, 1,1), ALIKAHN(1,1, 15,6, 30,10, 12,6), LORASAADI(1,1, 1,1, 3,2, 2,1), - MOONSHADOW(4,2, 1,1, 8,8, 10,5), + MOONSHADOW(4,2, 1,1, 8,8, 15,7), GLADOMAIN(1,1, 12,10, 8,8, 1,1); int baseval; @@ -381,12 +381,12 @@ public enum ItemSet { lore.add(ChatColor.GOLD+""+ChatColor.ITALIC+"Set Bonus:"); lore.add(ChatColor.DARK_AQUA+" 2 - "+ChatColor.WHITE+" +"+ItemSet.GetBaseAmount(set, tier, 2)+"% Cooldown Reduction"); lore.add(ChatColor.DARK_AQUA+" 3 - "+ChatColor.WHITE+" +"+ItemSet.GetBaseAmount(set, tier, 3)+"% Dodge Chance"); - lore.add(ChatColor.DARK_AQUA+" 5 - "+ChatColor.WHITE+" Life Saver "+WorldShop.toRomanNumeral(ItemSet.GetBaseAmount(set, tier, 4))+""); + lore.add(ChatColor.DARK_AQUA+" 5 - "+ChatColor.WHITE+" Life Saver "); lore.add(ChatColor.GRAY+" When about to be killed, puts you into"); lore.add(ChatColor.GRAY+" stealth, applies Speed IV for 10 seconds, adds"); lore.add(ChatColor.GRAY+" invulnerability, and de-aggros all current"); lore.add(ChatColor.GRAY+" targets."); - lore.add(ChatColor.WHITE+" 3 Minute Cooldown"); + lore.add(ChatColor.WHITE+" 5 Minute Cooldown"); lore.add(ChatColor.DARK_AQUA+" 7 - "+ChatColor.WHITE+" Provides the Following Bonuses:"); lore.add(ChatColor.GRAY+" "+ChatColor.WHITE+"A successful Assassination grants 100%"); lore.add(ChatColor.GRAY+" "+ChatColor.WHITE+"Critical Strike Chance and 100% Dodge"); diff --git a/src/sig/plugin/TwosideKeeper/TwosideKeeper.java b/src/sig/plugin/TwosideKeeper/TwosideKeeper.java index 32b916c..2575a0e 100644 --- a/src/sig/plugin/TwosideKeeper/TwosideKeeper.java +++ b/src/sig/plugin/TwosideKeeper/TwosideKeeper.java @@ -50,6 +50,7 @@ import org.bukkit.entity.Snowball; import org.bukkit.entity.ThrownPotion; import org.bukkit.entity.TippedArrow; import org.bukkit.entity.Witch; +import org.bukkit.entity.Zombie; import org.bukkit.entity.minecart.HopperMinecart; import org.bukkit.event.Event.Result; import org.bukkit.event.EventHandler; @@ -144,6 +145,7 @@ import net.md_5.bungee.api.chat.ClickEvent; import net.md_5.bungee.api.chat.ComponentBuilder; import net.md_5.bungee.api.chat.HoverEvent; import net.md_5.bungee.api.chat.TextComponent; +import sig.plugin.TwosideKeeper.Boss.MegaWither; import sig.plugin.TwosideKeeper.HelperStructures.AnvilItem; import sig.plugin.TwosideKeeper.HelperStructures.ArtifactAbility; import sig.plugin.TwosideKeeper.HelperStructures.ArtifactItem; @@ -553,7 +555,7 @@ public class TwosideKeeper extends JavaPlugin implements Listener { public static final int LINEDRIVE_COOLDOWN=240; public static final int REJUVENATE_COOLDOWN=2400; public static final int ASSASSINATE_COOLDOWN=200; - public static final int LIFESAVER_COOLDOWN=3600; + public static final int LIFESAVER_COOLDOWN=6000; public static File filesave; public static HashMap playerdata; @@ -1338,6 +1340,11 @@ public class TwosideKeeper extends JavaPlugin implements Listener { em.runPlayerLeaveEvent(ev.getPlayer()); } + for (UUID id : livingentitydata.keySet()) { + LivingEntityStructure les = LivingEntityStructure.getLivingEntityStructure(livingentitydata.get(id).m); + les.setGlow(ev.getPlayer(), null); + } + for (Player p :Bukkit.getOnlinePlayers()) { if (p!=null) { p.playSound(p.getLocation(), Sound.BLOCK_NOTE_PLING, 8, 0.7f); @@ -3917,16 +3924,15 @@ public class TwosideKeeper extends JavaPlugin implements Listener { if (ev.getCause()!=DamageCause.CUSTOM) { //This is not handled damage, so apply it. double dmgdealt = ev.getDamage(DamageModifier.BASE); CustomDamage.setupTrueDamage(ev); - //boolean applieddmg = CustomDamage.ApplyDamage(dmgdealt, null, (LivingEntity)ev.getEntity(), null, ev.getCause().name(), CustomDamage.TRUEDMG); if (!CustomDamage.InvulnerableCheck(null, (LivingEntity)ev.getEntity())) { boolean applieddmg=true; - dmgdealt = CustomDamage.CalculateDamage(dmgdealt, null, (LivingEntity)ev.getEntity(), null, null, CustomDamage.NONE); + dmgdealt = CustomDamage.CalculateDamage(dmgdealt, null, (LivingEntity)ev.getEntity(), null, null, CustomDamage.TRUEDMG); if (ev.getCause()==DamageCause.FALL) { dmgdealt *= GenericFunctions.CalculateFallResistance((LivingEntity)ev.getEntity()); } dmgdealt = CustomDamage.subtractAbsorptionHearts(dmgdealt, (LivingEntity)ev.getEntity()); - dmgdealt = CustomDamage.applyOnHitEffects(dmgdealt,null,(LivingEntity)ev.getEntity(),null ,null,CustomDamage.NONE); + dmgdealt = CustomDamage.applyOnHitEffects(dmgdealt,null,(LivingEntity)ev.getEntity(),null ,null,CustomDamage.TRUEDMG); if ((ev.getCause()==DamageCause.CONTACT || ev.getCause()==DamageCause.LIGHTNING || ev.getCause()==DamageCause.FALLING_BLOCK || @@ -4265,7 +4271,7 @@ public class TwosideKeeper extends JavaPlugin implements Listener { } else { log("This monster is "+MonsterController.getMonsterDifficulty(m).name(),5); if (MonsterController.getMonsterDifficulty(m)==MonsterDifficulty.ELITE) { - EliteMonster em = new EliteMonster(m); + EliteMonster em = GenericFunctions.getProperEliteMonster(m); ms.SetElite(true); elitemonsters.add(em); } diff --git a/src/sig/plugin/TwosideKeeper/TwosideKeeperAPI.java b/src/sig/plugin/TwosideKeeper/TwosideKeeperAPI.java index 100939d..9983d8b 100644 --- a/src/sig/plugin/TwosideKeeper/TwosideKeeperAPI.java +++ b/src/sig/plugin/TwosideKeeper/TwosideKeeperAPI.java @@ -423,6 +423,9 @@ public final class TwosideKeeperAPI { public static String getLocalizedItemName(Material i, short data) { return GenericFunctions.UserFriendlyMaterialName(i,data); } + public static ItemStack convertPotionEffectsToLore(ItemStack item) { + return GenericFunctions.AddCustomPotionTag(item); + } //Player COMMANDS. public static double getPlayerVelocity(Player p) { diff --git a/src/sig/plugin/TwosideKeeper/runServerHeartbeat.java b/src/sig/plugin/TwosideKeeper/runServerHeartbeat.java index 0361e3f..6444281 100644 --- a/src/sig/plugin/TwosideKeeper/runServerHeartbeat.java +++ b/src/sig/plugin/TwosideKeeper/runServerHeartbeat.java @@ -329,7 +329,7 @@ final class runServerHeartbeat implements Runnable { } } if (!hasstruct) { - TwosideKeeper.elitemonsters.add(new EliteMonster((Monster)(ms.m))); + TwosideKeeper.elitemonsters.add(GenericFunctions.getProperEliteMonster((Monster)(ms.m))); } } }