bugs added. Full Notes: +>Party Matching now does not create a party until at least two players are within the vicinity of each other. This effectively increases the cap of players in parties from 16 players to 32 players, if all 16 parties were filled with 2 players each. +>Added the EntityDamagedEvent which returns the amount of damage an entity takes and the cause of the damage. This is also cancellable which will prevent the entity from losing health and prevents on-hit effects from being applied. +>Added isWorldShopSign() to the API to detect if a sign is attached to a world shop. +>Added getWorldShopItemBasePrice() to the API. Returns the base price of any item using the new world shop pricing system. +>Added LivingEntity versions of all Monster commands to the API. +>The beginning stages of gearing can be a pain as you can get one shot by most mobs at the Dangerous tier even with some iron pieces. While one solution may be to lower the damage output of Dangerous monsters, it seems the drops are good enough to justify the difficulty of this range. Instead we decided to decrease the gearing gap between Leather/Iron versus Diamond/Gold. This provides players with more meaningful upgrade routes and makes damage reduction feel more impactful early game. After all, the first 30% of defense hardly matters. The scale went from looking like this: L3<I5<LH6<D8<G10<IH10<DH16<GH20 TO THIS: L6<I7<D8<G10<LH12<IH14<DH16<GH20 Progression-wise, the second scale makes more sense as it keeps the armor upgrades in the same order while emphasizing that any Hardened piece is automatically better than a regular Gold piece. +>Flat Damage Reduction from Leather armor increased from 3/6% per piece (Regular/Hardened) to 6/12% per piece. +>Flat Damage Reduction from Iron armor increased from 5/10% per piece to 7/14% per piece. +>Fire eruptions now occur in the Nether to liven up the tame lava seas. +>Fire Protection now actually reduces damage dealt by fires. This is actually very important with the update below! +>Fire and Lava now increases your fire ticks indefinitely, therefore the longer you stay in lava, the longer you will burn until it gets removed! +>Fire ticks will deal more damage the larger your fire tick count is! This is mitigated heavily by Fire Protection on armor. Do NOT stand in fire too long or YOU WILL die! +>Fire tick stacks now show up in the action bar. +>World Shops have been revamped. World Shop prices are now controlled externally and can be rebalanced and modified at any time. Signs will reflect these changes when viewing the items. +>Any player can now place and remove world shops, the shop will automatically be setup. Crafting Recipe for a world shop is <ITEM>+Chest/Trapped Chest+Sign. <ITEM> can be any item. +>Prices of World Shops dynamically change based on the location the shop in relation to the center of Twoside. Every 10000 blocks away doubles the price of the item. Going underground increases the price by 50% per difficulty level. Placing a world shop in another dimension multiplies the price by x4. +>The 'Deal of the Day' has been added as an incentive to purchase items from world shops on certain days. Keep an eye out for an item you may want to purchase! The item will be discounted everywhere regardless of location! +>Players that can attack on a moment's notice can make the most use of a weapon's damage. Sprinting and attacking from mid-air deals 20% more damage. +>Some sound effects regarding combat has been globalized so all nearby players can hear the action that is going on. +>The Tactics job now has bonuses activated on all combat stats. +>Fixed Localization of the different versions of the Anvil. (Slightly Damaged and Very Damaged) +>Added a new version of the 'Earth Wave' artifact ability. Damage scaling decreased, but has huge AoE potential and deals double damage on soft ground. Has no cooldown, but difficult to use without a height advantage. +>Added in Vacuum Cubes and Filter Cubes. See '/craft' for the crafting recipes of these two new Cubes. Vacuum Cubes only store placeable blocks and suck up all nearby items. Filter Cubes have a special inventory accessed by shift-right clicking which will automatically insert items of the same type into its inventory automatically! +>All entity types can now be modified with difficulty tags, this means Deadly Horses, Dangerous Wolves, and Hellfire Slimes (and many more!) are now a thing. +>Nether difficulty spawning rules have been added: As you get further and further away from the main hub in the Nether, the monsters increase in difficulty. No longer depth-dependent like in the Overworld. +>Health of all monsters within the Nether world have been increased significantly. +>Hellfire Ghast behavior has been modified. They now shoot faster fireballs and at a much faster rate. They will also attempt to suicide when low. +>Blaze behavior has been modified. Blazes fire more fireballs, and they explode on contact now. In addition, Hellfire Blazes now set the area on fire temporarily. +>Magma Cubes now buff all nearby monsters with higher defenses. 20%/40%/60%/80% damage reduction for Normal/Dangerous/Deadly/Hellfire tiers respectively. +>The item drop rate in the Nether has been increased by 30%. >Diamond armor (8/16% per piece) and Gold armor (10/20% per piece) defense values remain the same. >The Hunter's Compass is now more aggressive at looking for Elite spawn locations. >Fixed a bug causing the artifact ability leveling menu to never appear for artifacts T11 or higher. >Fixed a bug causing shop purchase notifications to crash the server if certain conditions are met. >Fixed a bug causing arrow quivers to mysteriously vanish from players' inventories when running out of arrows. >Fixed a bug causing Ranger gear to drop with a lower tier rate than other items. >Fixed a bug causing Non-Monster creatures to create errors when attempting to use Eruption on them. >Fixed a bug causing the party bonus to not increase damage to party members. >Fixed a bug preventing Artifact armor from losing durability from all sources of damage. >Fixed a bug causing errors when using name tags on non-hostile creatures. >Fixed a bug where the cooldown indicator for the Eruption ability was not properly adjusting with increased cooldown reduction. >Fixed a bug preventing players from inserting items into Item Cubes when the ID of the Item Cube window they are viewing is the same as the ID of the cube they are inserting into. >Fixed a bug where players were receiving damage reduction by holding armor in their hand. >Moved Arrow Quivers from the Misc. Items category to the Containers category in the /craft menu. >Modified heart display of mobs to display transparent hearts for missing health. >Fixed bugs relating to players being unable to obtain all achievements due to plugins manipulating them. >Fixed a bug preventing Slime and Magma Cube splits from happening properly when they die. ->Decreased the chance Coal dropped from monsters significantly. ->Decreased the chance Ender Chests dropped from monsters significantly. ->Decreased the drop rate of tier-less/surface monsters. ->Ranger Base Dodge Chance decreased from 50%->40%. ->Proper footing is important to maximizing damage. Attacks from mid-air now deal 20% less damage when not sprinting. ->Ranger Invincibility Time on Tumble with a full set decreased from 3 seconds -> 1.5 seconds. ->Deprecated all Monster versions of the Monster commands in the API. The newer system uses Living Entities instead.testdev
parent
aa25cf1792
commit
a15d7dd735
Binary file not shown.
@ -1,10 +1,306 @@ |
||||
package sig.plugin.TwosideKeeper.HelperStructures; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
import org.bukkit.Bukkit; |
||||
import org.bukkit.Material; |
||||
import org.bukkit.entity.Entity; |
||||
import org.bukkit.entity.LivingEntity; |
||||
import org.bukkit.entity.Monster; |
||||
import org.bukkit.entity.Player; |
||||
import org.bukkit.inventory.ItemStack; |
||||
import org.bukkit.inventory.meta.SkullMeta; |
||||
|
||||
import aPlugin.API.Chests; |
||||
import net.md_5.bungee.api.ChatColor; |
||||
import sig.plugin.TwosideKeeper.CustomDamage; |
||||
import sig.plugin.TwosideKeeper.MonsterController; |
||||
import sig.plugin.TwosideKeeper.TwosideKeeper; |
||||
import sig.plugin.TwosideKeeper.HelperStructures.Common.GenericFunctions; |
||||
|
||||
public enum LivingEntityDifficulty { |
||||
NORMAL, |
||||
DANGEROUS, |
||||
DEADLY, |
||||
HELLFIRE, |
||||
ELITE, |
||||
END; |
||||
NORMAL(0), |
||||
DANGEROUS(500), |
||||
DEADLY(1000), |
||||
HELLFIRE(5000), |
||||
ELITE(10000), |
||||
END(6000); |
||||
|
||||
int rating; |
||||
|
||||
LivingEntityDifficulty(int rating) { |
||||
this.rating=rating; |
||||
} |
||||
|
||||
/*private ItemStack Artifact() { |
||||
sig.plugin.TwosideKeeper.Artifact.createArtifactItem(ArtifactItem.ARTIFACT_ESSENCE,3); |
||||
return null; |
||||
}*/ |
||||
|
||||
public int getRating() { |
||||
return rating; |
||||
} |
||||
|
||||
/** |
||||
* Returns whether diff is stronger than the current difficulty. This is a numerical comparison, |
||||
* and so will always be accurate. |
||||
*/ |
||||
public boolean isStronger(LivingEntityDifficulty diff) { |
||||
return (this.getRating()>diff.getRating()); |
||||
} |
||||
|
||||
public List<ItemStack> RandomizeDrops(double dropmult, boolean isBoss, boolean isRanger, Entity damager, LivingEntity m) { |
||||
return RandomizeDrops(dropmult,isBoss,false,isRanger,damager,m); |
||||
} |
||||
|
||||
public List<ItemStack> RandomizeDrops(double dropmult, boolean isBoss, boolean isElite, boolean isRanger, Entity damager, LivingEntity m) { |
||||
|
||||
LivingEntityDifficulty diff = MonsterController.getLivingEntityDifficulty(m); |
||||
|
||||
TwosideKeeper.log(ChatColor.AQUA+"->Entering RandomizeDrops()", 5); |
||||
List<ItemStack> droplist = new ArrayList<ItemStack>(); |
||||
dropmult += 1; //Base dropmult is 1.0.
|
||||
if (Math.random() < dropmult % 1) |
||||
{ |
||||
dropmult++; |
||||
} |
||||
|
||||
//Basically for each additional dropmult integer value, the
|
||||
//amount of rolls increases. (A dropmult of 1.0 is required for
|
||||
//an additional roll.)
|
||||
Player p = (Player)CustomDamage.getDamagerEntity(damager); |
||||
for (int i=0;i<dropmult;i++) { |
||||
TwosideKeeper.Loot_Logger.AddLootRoll(); |
||||
TwosideKeeper.log("Attempting a roll...", TwosideKeeper.LOOT_DEBUG); |
||||
ItemStack goodie = null; |
||||
if (Math.random()<=0.1 || isBoss) { |
||||
TwosideKeeper.log("Inside!", 5); |
||||
switch (diff) { |
||||
case DANGEROUS:{ |
||||
goodie=aPlugin.API.Chests.LOOT_DANGEROUS.getSingleDrop(p); |
||||
KeepRollingForBosses(isBoss, droplist, goodie, aPlugin.API.Chests.LOOT_DANGEROUS, p); |
||||
}break; |
||||
case DEADLY:{ |
||||
goodie=aPlugin.API.Chests.LOOT_DEADLY.getSingleDrop(p); |
||||
KeepRollingForBosses(isBoss, droplist, goodie, aPlugin.API.Chests.LOOT_DEADLY, p); |
||||
}break; |
||||
case HELLFIRE:{ |
||||
goodie=aPlugin.API.Chests.LOOT_HELLFIRE.getSingleDrop(p); |
||||
KeepRollingForBosses(isBoss, droplist, goodie, aPlugin.API.Chests.LOOT_HELLFIRE, p); |
||||
}break; |
||||
case END:{ |
||||
goodie=aPlugin.API.Chests.LOOT_CUSTOM.getSingleDrop(p); |
||||
KeepRollingForBosses(isBoss, droplist, goodie, aPlugin.API.Chests.LOOT_CUSTOM, p); |
||||
}break; |
||||
case ELITE:{ |
||||
|
||||
}break; |
||||
default:{ |
||||
if (Math.random()<=0.4) { |
||||
goodie=aPlugin.API.Chests.LOOT_NORMAL.getSingleDrop(p); |
||||
} |
||||
KeepRollingForBosses(isBoss, droplist, goodie, aPlugin.API.Chests.LOOT_NORMAL, p); |
||||
} |
||||
} |
||||
TwosideKeeper.Loot_Logger.AddCommonLoot(); |
||||
ModifyAndAddDropToList(droplist,goodie,damager); |
||||
} |
||||
} |
||||
TwosideKeeper.log("New Droplist: "+droplist.toString(), 5); |
||||
return droplist; |
||||
} |
||||
|
||||
public void KeepRollingForBosses(boolean isBoss, List<ItemStack> droplist, ItemStack goodie, Chests chest, Player damager) { |
||||
int roll=0; |
||||
while (isBoss && !isValidSetItem(goodie) && roll<50) { |
||||
goodie=chest.getSingleDrop(damager); |
||||
ModifyAndAddDropToList(droplist,goodie,damager); |
||||
roll++; |
||||
TwosideKeeper.Loot_Logger.AddCommonLoot(); |
||||
} |
||||
} |
||||
|
||||
private void ModifyAndAddDropToList(List<ItemStack> droplist, ItemStack goodie, Entity damager) { |
||||
/*LivingEntity shooter = CustomDamage.getDamagerEntity(damager); |
||||
if (shooter instanceof Player) { |
||||
Player p = (Player)shooter; |
||||
if (isValidSetItem(goodie)) { |
||||
if (Math.random()<0.8) { |
||||
//Convert it to a set piece.
|
||||
PlayerMode pm = PlayerMode.getPlayerMode(p); |
||||
if (AllowedToConvert(pm,goodie)) { |
||||
ItemSet set = PickAnItemSet(pm,goodie); |
||||
goodie = ConvertSetPieceIfNecessary(goodie, set); |
||||
goodie = Loot.GenerateSetPiece(goodie.getType(), set, (Math.random()<0.1)?true:false, 0, false); |
||||
} |
||||
} else { |
||||
//Convert it to a mega piece.
|
||||
PlayerMode pm = PlayerMode.getPlayerMode(p); |
||||
if (AllowedToConvert(pm,goodie)) { |
||||
goodie = Loot.GenerateMegaPiece(goodie.getType(), (Math.random()<0.1)?true:false); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
TwosideKeeper.log("Adding item "+goodie, 2);*/ //LEGACY CODE.
|
||||
droplist.add(goodie); |
||||
} |
||||
|
||||
@SuppressWarnings("unused") |
||||
private boolean AllowedToConvert(PlayerMode pm, ItemStack goodie) { |
||||
if (goodie.getType()==Material.SKULL_ITEM && pm!=PlayerMode.NORMAL && pm!=PlayerMode.SLAYER) { |
||||
goodie.setDurability((short)3); |
||||
SkullMeta sm = (SkullMeta)goodie.getItemMeta(); |
||||
sm.setOwner(Bukkit.getOfflinePlayers()[(int)(Math.random()*Bukkit.getOfflinePlayers().length)].getName()); |
||||
goodie.setItemMeta(sm); |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
public static ItemStack ConvertSetPieceIfNecessary(ItemStack goodie, ItemSet set) { |
||||
if ((set==ItemSet.JAMDAK || |
||||
set==ItemSet.ALIKAHN || |
||||
set==ItemSet.DARNYS || |
||||
set==ItemSet.LORASAADI) && |
||||
!goodie.getType().name().contains("LEATHER") && |
||||
GenericFunctions.isArmor(goodie)) { |
||||
goodie.setType(Material.valueOf("LEATHER_"+goodie.getType().name().split("_")[1])); |
||||
} else |
||||
if (goodie.getType().name().contains("LEATHER") && |
||||
!(set==ItemSet.JAMDAK || |
||||
set==ItemSet.ALIKAHN || |
||||
set==ItemSet.DARNYS || |
||||
set==ItemSet.LORASAADI) && |
||||
GenericFunctions.isArmor(goodie)) { |
||||
goodie.setType(Material.valueOf("IRON_"+goodie.getType().name().split("_")[1])); |
||||
} else |
||||
if (goodie.getType()!=Material.SKULL_ITEM && |
||||
(set==ItemSet.MOONSHADOW || |
||||
set==ItemSet.GLADOMAIN || |
||||
set==ItemSet.WOLFSBANE || |
||||
set==ItemSet.ALUSTINE)) { |
||||
goodie.setType(Material.SKULL_ITEM); |
||||
} |
||||
return goodie; |
||||
} |
||||
|
||||
private boolean isValidSetItem(ItemStack goodie) { |
||||
if (goodie!=null) { |
||||
return TwosideKeeper.validsetitems.contains(goodie.getType()); |
||||
} else { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
public static ItemSet PickAnItemSet(PlayerMode pm, LivingEntityDifficulty md) { |
||||
ItemSet set; |
||||
switch (pm) { |
||||
case STRIKER:{ |
||||
set = ItemSet.PANROS; |
||||
}break; |
||||
case DEFENDER:{ |
||||
set = ItemSet.SONGSTEEL; |
||||
}break; |
||||
case BARBARIAN:{ |
||||
set = ItemSet.DAWNTRACKER; |
||||
}break; |
||||
case RANGER:{ |
||||
final int NUMBER_OF_MODES=4; |
||||
int totalweight=50*NUMBER_OF_MODES; //50 for each mode.
|
||||
int selectweight=(int)(Math.random()*totalweight); |
||||
if (selectweight<50) { |
||||
set = ItemSet.JAMDAK; |
||||
} else |
||||
if (selectweight<100) { |
||||
set = ItemSet.ALIKAHN; |
||||
} else |
||||
if (selectweight<150) { |
||||
set = ItemSet.DARNYS; |
||||
} else |
||||
{ |
||||
set = ItemSet.LORASAADI; |
||||
} |
||||
}break; |
||||
case SLAYER:{ |
||||
final int NUMBER_OF_MODES=3; |
||||
int totalweight=50*NUMBER_OF_MODES; //50 for each mode.
|
||||
int selectweight=(int)(Math.random()*totalweight); |
||||
if (selectweight<10) { |
||||
set = ItemSet.LORASYS; |
||||
} else |
||||
switch (md) { |
||||
case DANGEROUS:{ |
||||
set = ItemSet.ALUSTINE; |
||||
} |
||||
case DEADLY:{ |
||||
set = ItemSet.MOONSHADOW; |
||||
} |
||||
case HELLFIRE: |
||||
case END:{ |
||||
set = ItemSet.GLADOMAIN; |
||||
} |
||||
default:{ |
||||
set = ItemSet.WOLFSBANE; |
||||
} |
||||
} |
||||
}break; |
||||
default:{ |
||||
set = PickRandomSet(md); |
||||
} |
||||
} |
||||
return set; |
||||
} |
||||
|
||||
public static ItemSet PickRandomSet(LivingEntityDifficulty md) { |
||||
final int NUMBER_OF_MODES=5; |
||||
int totalweight=50*NUMBER_OF_MODES; //50 for each mode.
|
||||
int selectweight=(int)(Math.random()*totalweight); |
||||
if (selectweight<50) { |
||||
return ItemSet.PANROS; |
||||
} else |
||||
if (selectweight<100) { |
||||
return ItemSet.SONGSTEEL; |
||||
} else |
||||
if (selectweight<150) { |
||||
return ItemSet.DAWNTRACKER; |
||||
} else |
||||
if (selectweight<200) { |
||||
//12.5 per set type.
|
||||
if (selectweight<162.5) { |
||||
return ItemSet.JAMDAK; |
||||
} else |
||||
if (selectweight<175) { |
||||
return ItemSet.ALIKAHN; |
||||
} else |
||||
if (selectweight<187.5) { |
||||
return ItemSet.DARNYS; |
||||
} else |
||||
if (selectweight<200) { |
||||
return ItemSet.LORASAADI; |
||||
} |
||||
} else |
||||
if (selectweight<250) { |
||||
if (selectweight<205) { |
||||
return ItemSet.LORASYS; |
||||
} else |
||||
switch (md) { |
||||
case DANGEROUS:{ |
||||
return ItemSet.ALUSTINE; |
||||
} |
||||
case DEADLY:{ |
||||
return ItemSet.MOONSHADOW; |
||||
} |
||||
case HELLFIRE: |
||||
case END:{ |
||||
return ItemSet.GLADOMAIN; |
||||
} |
||||
default:{ |
||||
return ItemSet.WOLFSBANE; |
||||
} |
||||
} |
||||
} |
||||
return ItemSet.PANROS; |
||||
} |
||||
} |
||||
|
@ -0,0 +1,36 @@ |
||||
package sig.plugin.TwosideKeeper.HelperStructures.Utils; |
||||
|
||||
import java.util.List; |
||||
|
||||
import org.bukkit.entity.Entity; |
||||
import org.bukkit.entity.EntityType; |
||||
import org.bukkit.entity.LivingEntity; |
||||
|
||||
import sig.plugin.TwosideKeeper.MonsterController; |
||||
import sig.plugin.TwosideKeeper.HelperStructures.LivingEntityDifficulty; |
||||
|
||||
public class EntityUtils { |
||||
public static int CountNearbyEntityType(EntityType type, Entity ent, double range) { |
||||
List<Entity> ents = ent.getNearbyEntities(range, range, range); |
||||
int count=0; |
||||
for (Entity e : ents) { |
||||
if (e.getType()==type) { |
||||
count++; |
||||
} |
||||
} |
||||
return count; |
||||
} |
||||
public static LivingEntityDifficulty GetStrongestNearbyEntityDifficulty(EntityType type, Entity ent, double range) { |
||||
List<Entity> ents = ent.getNearbyEntities(range, range, range); |
||||
LivingEntityDifficulty strongest = LivingEntityDifficulty.NORMAL; |
||||
for (Entity e : ents) { |
||||
if (e instanceof LivingEntity) { |
||||
LivingEntityDifficulty diff = MonsterController.getLivingEntityDifficulty((LivingEntity)e); |
||||
if (e.getType()==type && !strongest.isStronger(diff)) { |
||||
strongest = diff; |
||||
} |
||||
} |
||||
} |
||||
return strongest; |
||||
} |
||||
} |
@ -0,0 +1,29 @@ |
||||
package sig.plugin.TwosideKeeper.HelperStructures.Utils; |
||||
|
||||
import org.bukkit.Location; |
||||
import org.bukkit.util.Vector; |
||||
|
||||
import sig.plugin.TwosideKeeper.TwosideKeeper; |
||||
|
||||
public class MovementUtils { |
||||
public static Vector moveTowardsLocation(Location currloc, Location targetloc, double spd) { |
||||
/*double deltax = currloc.getX()-targetloc.getX(); |
||||
double deltay = currloc.getY()-targetloc.getY(); |
||||
double deltaz = currloc.getZ()-targetloc.getZ(); |
||||
//Move at max speed in each direction until it matches the delta.
|
||||
double velx = Math.min(Math.abs(deltax), spd)*Math.signum(deltax); |
||||
double vely = Math.min(Math.abs(deltax), spd)*Math.signum(deltay); |
||||
double velz = Math.min(Math.abs(deltax), spd)*Math.signum(deltaz); |
||||
return new Vector(-velx,-vely,-velz); //Flip the sign so we're moving towards the point instead of away from it.*/
|
||||
double a = currloc.getX()-targetloc.getX(); |
||||
double c = currloc.getY()-targetloc.getY(); |
||||
double b = currloc.getZ()-targetloc.getZ(); |
||||
double angle = Math.atan2(b, a); |
||||
double angle2 = Math.atan2(c, a); |
||||
double velz = spd * Math.sin(angle); |
||||
double velx = spd * Math.cos(angle); |
||||
double vely = spd * Math.sin(angle2); |
||||
//TwosideKeeper.log("New angle is "+angle, 0);
|
||||
return new Vector(-velx,-vely,-velz); |
||||
} |
||||
} |
@ -0,0 +1,29 @@ |
||||
package sig.plugin.TwosideKeeper.Monster; |
||||
|
||||
import org.bukkit.entity.LivingEntity; |
||||
|
||||
import sig.plugin.TwosideKeeper.CustomMonster; |
||||
import sig.plugin.TwosideKeeper.TwosideKeeper; |
||||
|
||||
public class Blaze extends CustomMonster{ |
||||
|
||||
private long lastFireball = 0; |
||||
|
||||
public Blaze(LivingEntity m) { |
||||
super(m); |
||||
this.lastFireball=TwosideKeeper.getServerTickTime(); |
||||
} |
||||
|
||||
public long getLastFireball() { |
||||
return lastFireball; |
||||
} |
||||
|
||||
public void resetLastFireball() { |
||||
this.lastFireball = TwosideKeeper.getServerTickTime(); |
||||
} |
||||
|
||||
public void runTick() { |
||||
|
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue