2016-08-10 00:42:09 -05:00

1583 lines
57 KiB
Java

package sig.plugin.TwosideKeeper;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Difficulty;
import org.bukkit.Effect;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.block.Block;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.Enderman;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.FallingBlock;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.MagmaCube;
import org.bukkit.entity.Monster;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.Skeleton;
import org.bukkit.entity.Slime;
import org.bukkit.entity.Spider;
import org.bukkit.entity.TippedArrow;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.entity.EntityDamageEvent.DamageModifier;
import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.util.Vector;
import org.inventivetalent.glow.GlowAPI;
import org.inventivetalent.glow.GlowAPI.Color;
import com.google.common.collect.Iterables;
import sig.plugin.TwosideKeeper.HelperStructures.ArtifactAbility;
import sig.plugin.TwosideKeeper.HelperStructures.ArtifactAbilityApplyEffects;
import sig.plugin.TwosideKeeper.HelperStructures.BowMode;
import sig.plugin.TwosideKeeper.HelperStructures.ItemSet;
import sig.plugin.TwosideKeeper.HelperStructures.MonsterDifficulty;
import sig.plugin.TwosideKeeper.HelperStructures.MonsterType;
import sig.plugin.TwosideKeeper.HelperStructures.Common.DamageType;
import sig.plugin.TwosideKeeper.HelperStructures.Common.GenericFunctions;
public class NewCombat {
/**
* Returns the amount of damage dealt to target.
*/
public static double applyDamage(LivingEntity target, Entity damager) {
switch (DamageType.DetectType(target, damager)) {
case MOBVSMOB:
case MOBPROJECTILEVSMOB:
case MOBPROJECTILEVSPLAYER:
case MOBVSPLAYER: {
return calculateMobDamage(target, damager);
}
case PLAYERPROJECTILEVSMOB:
case PLAYERVSMOB: {
return calculatePlayerDamage(target, damager);
}
case OTHER:
default: {
return -1.0;
}
}
}
//Set all damage modifiers from the game to 0. We will calculate our own value.
public static void setupTrueDamage(EntityDamageEvent ev) {
for (int i=0;i<DamageModifier.values().length;i++) {
if (ev.isApplicable(DamageModifier.values()[i])) {
ev.setDamage(DamageModifier.values()[i],0);
}
}
ev.setDamage(0);
}
public static double calculatePlayerDamage(LivingEntity target, Entity damager) {
LivingEntity shooter = getDamagerEntity(damager);
double finaldmg = 0.0;
if (shooter!=null) {
finaldmg += calculateTotalDamage(target, damager);
if (shooter instanceof Player) {
Player p = (Player)shooter;
playerPerformMiscActions(p,target);
if (target instanceof Monster) {
Monster m = (Monster)target;
setMonsterTarget(m,p);
provokeMonster(m,p);
}
}
}
if (shooter!=null) {
if (shooter instanceof Player) {
PlayerStructure pd = PlayerStructure.GetPlayerStructure((Player)shooter);
pd.damagedata.addCalculatedTotalDamage(finaldmg);
}
}
return finaldmg;
}
public static double calculateMobDamage(LivingEntity target, Entity damager) {
double totaldmg = 0.0;
double bonusmult = 1.0;
LivingEntity shooter = getDamagerEntity(damager);
if (shooter!=null) {
totaldmg += calculateMobBaseDamage((LivingEntity)shooter, target);
//totaldmg += CalculateWeaponDamage(shooter, target);
bonusmult *= calculateMonsterDifficultyMultiplier(shooter);
} else {
totaldmg = 1.0;
}
double finaldmg = calculateBonusMultiplier(totaldmg,bonusmult);
playerAddArtifactEXP(target,finaldmg);
applyOnHitMobEffects(target,damager,finaldmg);
finaldmg = CalculateDamageReduction(finaldmg,target,damager);
return calculateAbsorptionHearts(target, finaldmg);
}
static double calculateTotalDamage(LivingEntity target, Entity damager) {
double totaldmg = 0.0; //Final damage dealt. It will be multiplied by mult at the end.
double bonusmult = 1.0; //Bonus multiplier for damage dealt.
double armorpendmg = 0.0;
LivingEntity shooter = getDamagerEntity(damager);
if (shooter!=null) {
if (shooter instanceof Player) {
Player p = (Player)shooter;
ItemStack weapon = p.getEquipment().getItemInMainHand();
totaldmg+=CalculateWeaponDamage(damager, target);
double mult1 = calculatePlayerCriticalStrike(weapon,damager);
addMultiplierToPlayerLogger(damager,"Critical Strike Mult",mult1);
if (mult1>1.0) {
aPlugin.API.critEntity(target, 15);
PlayerStructure.GetPlayerStructure(p).crit=true;
}
bonusmult*=mult1;
}
}
if (shooter!=null) {
if (shooter instanceof Player) {
double dmg = calculateBonusMultiplier(totaldmg,bonusmult);
PlayerStructure pd = PlayerStructure.GetPlayerStructure((Player)shooter);
pd.damagedata.addCalculatedActualDamage(dmg);
}
}
double finaldmg = calculateBonusMultiplier(totaldmg,bonusmult);
if (damager instanceof Player) {
Player p = (Player)damager;
armorpendmg = calculateArmorPen(p, finaldmg);
}
return CalculateDamageReduction(finaldmg-armorpendmg,target,damager) +
armorpendmg;
}
static double calculateMobBaseDamage(LivingEntity damager, LivingEntity target) {
double dmg = 0.0;
Difficulty diff = damager.getWorld().getDifficulty();
double[] difficulty_damage = {0.0,0.0,0.0}; //Damager per difficulty. {EASY,MEDIUM,HARD}
switch (damager.getType()) {
case BLAZE:
difficulty_damage=new double[]{4.0,8.0,12.0};
break;
case CAVE_SPIDER:
difficulty_damage=new double[]{2.0,2.0,3.0};
break;
case CREEPER:
case LIGHTNING:
if (damager instanceof Creeper) {
Creeper c = (Creeper)damager;
double damage_mult = 2.0d/(c.getLocation().distance(target.getLocation())+1.0);
damage_mult*=TwosideKeeper.EXPLOSION_DMG_MULT;
difficulty_damage = (c.isPowered())?new double[]{48.0*damage_mult,72.0*damage_mult,98.0*damage_mult}:new double[]{24.0*damage_mult,36.0*damage_mult,49.0*damage_mult};
} else {
difficulty_damage=new double[]{12.0,18.0,24.0};
}
break;
case DRAGON_FIREBALL:
case ENDER_DRAGON:
difficulty_damage=new double[]{6.0,12.0,24.0};
break;
case ENDERMAN:
difficulty_damage=new double[]{4.0,7.0,12.0};
break;
case ENDERMITE:
difficulty_damage=new double[]{2.0,3.0,4.0};
break;
case ENDER_CRYSTAL:
difficulty_damage=new double[]{24.0,36.0,49.0};
break;
case FALLING_BLOCK:
difficulty_damage=new double[]{2.0,4.0,6.0};
break;
case FIREBALL:
case SMALL_FIREBALL:
difficulty_damage=new double[]{9.0,17.0,25.0};
break;
case GHAST:
difficulty_damage=new double[]{10.0,20.0,30.0};
break;
case GUARDIAN:
difficulty_damage=new double[]{4.0,7.0,10.0};
break;
case MAGMA_CUBE:
MagmaCube mc = (MagmaCube)damager;
difficulty_damage=new double[]{mc.getSize(),mc.getSize()*2.0,mc.getSize()*4.0};
break;
case PIG_ZOMBIE:
difficulty_damage=new double[]{5.0,9.0,13.0};
break;
case RABBIT:
difficulty_damage=new double[]{6.0,12.0,20.0};
break;
case SHULKER:
difficulty_damage=new double[]{8.0,16.0,24.0};
break;
case SHULKER_BULLET:
difficulty_damage=new double[]{8.0,16.0,24.0};
break;
case SILVERFISH:
difficulty_damage=new double[]{1.0,2.0,4.0};
break;
case SKELETON:
Skeleton s = (Skeleton)damager;
switch (s.getSkeletonType()) {
case NORMAL:
difficulty_damage=new double[]{2.0,2.0,4.0};
break;
case WITHER:
difficulty_damage=new double[]{4.0,8.0,12.0};
break;
default:
difficulty_damage=new double[]{8.0,10.0,12.0};
break;
}
break;
case SLIME:
Slime sl = (Slime)damager;
difficulty_damage=new double[]{sl.getSize(),sl.getSize()*3.0,sl.getSize()*5.0};
break;
case SPIDER:
difficulty_damage=new double[]{2.0,4.0,6.0};
break;
case WOLF:
case WITCH:
difficulty_damage=new double[]{3.0,5.0,7.0};
break;
case WITHER:
difficulty_damage=new double[]{10.0,16.0,36.0};
break;
case WITHER_SKULL:
difficulty_damage=new double[]{10.0,16.0,36.0};
break;
case GIANT:
case ZOMBIE:
difficulty_damage=new double[]{2.0,3.0,5.0};
break;
default:
difficulty_damage=new double[]{1.0,1.5,2.0};
break;
}
switch (diff) {
case EASY:
dmg+=difficulty_damage[0];
break;
case HARD:
dmg+=difficulty_damage[2];
break;
case NORMAL:
dmg+=difficulty_damage[1];
break;
}
return dmg;
}
static double calculateMonsterDifficultyMultiplier(LivingEntity damager) {
double mult = 1.0;
if (damager instanceof Monster) {
switch (MonsterController.getMonsterDifficulty((Monster)damager)) {
case NORMAL:
mult*=1.0;
break;
case DANGEROUS:
mult*=2.0;
break;
case DEADLY:
mult*=5.0;
break;
case HELLFIRE:
mult*=10.0;
break;
case ELITE:
mult*=40.0;
break;
default:
mult*=1.0;
break;
}
}
return mult;
}
private static double calculateArmorPen(Player p, double dmg) {
double finaldmg = 0.0;
if (GenericFunctions.isArtifactEquip(p.getEquipment().getItemInMainHand()) &&
ArtifactAbility.containsEnchantment(ArtifactAbility.ARMOR_PEN, p.getEquipment().getItemInMainHand())) {
finaldmg += dmg*GenericFunctions.getAbilityValue(ArtifactAbility.ARMOR_PEN, p.getEquipment().getItemInMainHand())/100d;
addToPlayerLogger(p,"Armor Pen",finaldmg);
}
return finaldmg;
}
static void playerPerformMiscActions(Player p, Entity target) {
//GenericFunctions.PerformDodge(p);
castEruption(p, target);
removePermEnchantments(p);
}
private static void removePermEnchantments(Player p) {
if (GenericFunctions.isWeapon(p.getEquipment().getItemInMainHand())) {
GenericFunctions.RemovePermEnchantmentChance(p.getEquipment().getItemInMainHand(), p);
}
}
private static void castEruption(Player p, Entity target) {
PlayerStructure pd = PlayerStructure.GetPlayerStructure(p);
if (GenericFunctions.isArtifactEquip(p.getEquipment().getItemInMainHand()) &&
p.getEquipment().getItemInMainHand().getType().toString().contains("SPADE") && p.isSneaking()) {
if (ArtifactAbility.containsEnchantment(ArtifactAbility.ERUPTION, p.getEquipment().getItemInMainHand()) &&
pd.last_shovelspell<TwosideKeeper.getServerTickTime()) {
//Detect all nearby mobs and knock them up. Deal damage to them as well.
List<Entity> finallist = new ArrayList<Entity>();
List<Entity> nearby = target.getNearbyEntities(2, 2, 2);
for (int i=0;i<nearby.size();i++) {
if (nearby.get(i) instanceof Monster) {
finallist.add(nearby.get(i));
}
}
finallist.add(target);
for (int i=0;i<finallist.size();i++) {
Monster mon = (Monster)finallist.get(i);
double finaldmg = CalculateDamageReduction(GenericFunctions.getAbilityValue(ArtifactAbility.ERUPTION, p.getEquipment().getItemInMainHand()),mon,null);
addToPlayerLogger(p,ChatColor.BLUE+"Eruption",finaldmg);
GenericFunctions.DealDamageToMob(finaldmg, mon, p, p.getEquipment().getItemInMainHand());
mon.addPotionEffect(new PotionEffect(PotionEffectType.LEVITATION,20,15));
//Attempt to dig out the blocks below.
for (int x=-1;x<2;x++) {
for (int z=-1;z<2;z++) {
Block b = mon.getLocation().add(x,-1,z).getBlock();
if (aPlugin.API.isDestroyable(b) && GenericFunctions.isSoftBlock(b)) {
//log(b.getType()+" is destroyable.",2);
FallingBlock fb = (FallingBlock)b.getLocation().getWorld().spawnFallingBlock(b.getLocation().add(0,0.1,0),b.getType(),(byte)0);
fb.setVelocity(new Vector(0,Math.random()*1.35,0));
fb.setMetadata("FAKE", new FixedMetadataValue(TwosideKeeper.plugin,true));
//b.breakNaturally();
b.setType(Material.AIR);
aPlugin.API.sendSoundlessExplosion(b.getLocation(), 1);
p.playSound(mon.getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 1.0f, 1.0f);
}
}
}
}
p.playSound(p.getLocation(), Sound.ENTITY_FIREWORK_LARGE_BLAST, 1.0f, 1.0f);
aPlugin.API.sendCooldownPacket(p, p.getEquipment().getItemInMainHand(), 100);
aPlugin.API.sendCooldownPacket(p, p.getEquipment().getItemInMainHand(), 100);
pd.last_shovelspell=TwosideKeeper.getServerTickTime()+TwosideKeeper.ERUPTION_COOLDOWN;
}
}
}
static void setMonsterTarget(Monster m, Player p) {
addChargeZombieToList(m);
addMonsterToTargetList(m,p);
}
static void addChargeZombieToList(Monster m) {
if (MonsterController.isChargeZombie(m)) {
TwosideKeeper.chargezombies.add(new ChargeZombie((Monster)m));
}
}
public static void addMonsterToTargetList(Monster m,Player p) {
if (!m.hasPotionEffect(PotionEffectType.GLOWING)) {m.setTarget(p);}
if (TwosideKeeper.monsterdata.containsKey(m.getUniqueId())) {
MonsterStructure ms = (MonsterStructure)TwosideKeeper.monsterdata.get(m.getUniqueId());
ms.SetTarget(p);
} else {
TwosideKeeper.monsterdata.put(m.getUniqueId(),new MonsterStructure(m,p));
}
}
static void provokeMonster(Monster m, Player p) {
applyDefenderAggro(m,p);
applyProvokeAggro(m,p);
leaderRallyNearbyMonsters(m,p);
}
static void leaderRallyNearbyMonsters(Monster m, Player p) {
if (MonsterController.isZombieLeader(m) &&
!m.hasPotionEffect(PotionEffectType.GLOWING)) {
rallyNearbyMonsters(m,p,10);
}
}
private static void rallyNearbyMonsters(Monster m, Player p, double range) {
Collection<Entity> nearby =m.getLocation().getWorld().getNearbyEntities(m.getLocation(), range, range, range);
for (int i=0;i<nearby.size();i++) {
if (Iterables.get(nearby, i) instanceof Monster) {
Monster mm = (Monster)(Iterables.get(nearby, i));
mm.setTarget(p);
MonsterStructure ms = MonsterStructure.getMonsterStructure(mm);
ms.SetTarget(p);
}
}
}
static void applyDefenderAggro(Monster m, Player p) {
if (!m.hasPotionEffect(PotionEffectType.GLOWING) && GenericFunctions.isDefender(p)) {
setMonsterTarget(m,p);
setAggroGlowTickTime(m,100);
}
}
static void setAggroGlowTickTime(Monster m, int duration) {
m.addPotionEffect(new PotionEffect(PotionEffectType.GLOWING,duration,0));
}
static void applyProvokeAggro(Monster m, Player p) {
if (ArtifactAbilityApplyEffects.canExecuteArtifactAbility(ArtifactAbility.PROVOKE, p)) {
//This is allowed, get the level on the weapon.
int provokelv = ArtifactAbility.getEnchantmentLevel(ArtifactAbility.PROVOKE, p.getEquipment().getItemInMainHand());
setAggroGlowTickTime(m,ArtifactAbility.getEnchantmentLevel(ArtifactAbility.PROVOKE, p.getEquipment().getItemInMainHand())*20);
}
}
static double calculatePreemptiveStrikeMultiplier(LivingEntity m, Player p) {
double mult = 1.0;
if (isPreemptiveStrike(m,p)) {
//Deal triple damage.
TwosideKeeper.log("Triple damage!",5);
p.playSound(p.getLocation(), Sound.ENTITY_SHULKER_TELEPORT, 1f, 3.65f);
mult*=3.0;
addMultiplierToPlayerLogger(p,ChatColor.YELLOW+"Preemptive Strike Mult",mult);
}
return mult;
}
static boolean isPreemptiveStrike(LivingEntity m,Player p) {
if (GenericFunctions.isStriker(p) &&
m!=null &&
(m instanceof Monster) &&
((Monster)m).getTarget()==null) {
return true;
} else {
return false;
}
}
static double calculateBonusMultiplier(double dmg,double mult) {
//If we have a multiplier, use that. Otherwise use the base damage value.
return dmg*mult;
}
public static double CalculateWeaponDamage(Entity damager, LivingEntity target) {
return CalculateWeaponDamage(damager,target,false);
}
public static double CalculateWeaponDamage(Entity damager, LivingEntity target, boolean useBow) {
double basedmg = 0.0;
double basemult = 1.0;
boolean headshot=false;
boolean preemptive=false;
LivingEntity shooter = getDamagerEntity(damager);
if (shooter!=null) {
LivingEntity ent = shooter;
ItemStack weapon = ent.getEquipment().getItemInMainHand();
if (GenericFunctions.isArtifactEquip(weapon)) {
double dmg = getBaseArtifactDamageByType(weapon);
addToPlayerLogger(ent,"Weapon Base Damage",dmg);
basedmg += dmg;
} else {
double dmg = getBaseDamageByType(weapon);
addToPlayerLogger(ent,"Weapon Base Damage",dmg);
basedmg += dmg;
}
for (int i=0;i<GenericFunctions.getEquipment(shooter).length;i++) {
ItemSet set = ItemSet.GetSet(GenericFunctions.getEquipment(shooter)[i]);
if (set!=null) {
if (set==ItemSet.PANROS) {
double dmg = ItemSet.GetBaseAmount(set,ItemSet.GetTier(GenericFunctions.getEquipment(shooter)[i]),1);
addToPlayerLogger(ent,"Set Piece Damage",dmg);
basedmg += dmg;
}
}
}
if (shooter instanceof Player) {
Player p = (Player)shooter;
if (GenericFunctions.isDefender(p) && ItemSet.GetSetCount(ItemSet.SONGSTEEL, p)>=5) {
PlayerStructure pd = PlayerStructure.GetPlayerStructure(p);
if (pd.vendetta_amt>0.0) {
p.playSound(p.getLocation(), Sound.BLOCK_GLASS_BREAK, 1.0f, 0.5f);
double dmg = pd.vendetta_amt;
addToPlayerLogger(ent,"Vendetta",dmg);
basedmg += dmg;
pd.vendetta_amt=0.0;
aPlugin.API.sendActionBarMessage(p, ChatColor.YELLOW+"Vendetta: "+ChatColor.GREEN+Math.round(pd.vendetta_amt)+" dmg stored");
}
}
double dmg = ItemSet.TotalBaseAmountBasedOnSetBonusCount(p,ItemSet.PANROS,2,2);
addToPlayerLogger(ent,"Set Bonus",dmg);
basedmg += dmg;
dmg = ItemSet.TotalBaseAmountBasedOnSetBonusCount(p,ItemSet.DAWNTRACKER,2,2);
addToPlayerLogger(ent,"Set Bonus",dmg);
basedmg += dmg;
dmg = ItemSet.TotalBaseAmountBasedOnSetBonusCount(p,ItemSet.DAWNTRACKER,4,4);
addToPlayerLogger(ent,"Set Bonus",dmg);
basedmg += dmg;
}
if (GenericFunctions.isHardenedItem(weapon) && !GenericFunctions.isArtifactEquip(weapon)) {
double mult = 2.0;
addMultiplierToPlayerLogger(ent,"Hardened Item Mult",mult);
basemult*=mult;
}
if (ent instanceof Player) {
Player pl = (Player)ent;
basemult*=calculatePartyAttackMultiplier(pl);
basemult*=calculatePreemptiveStrikeMultiplier(target,pl);
if (target instanceof LivingEntity) {
preemptive = isPreemptiveStrike(target,pl);
}
}
basedmg+=calculateEnchantmentDamageIncrease(weapon,damager,target);
basedmg+=calculateArtifactAbilityDamageIncrease(weapon,damager,target);
basemult*=calculateArtifactAbilityMultiplier(weapon,damager,target);
basemult*=calculateStrikerMultiplier(damager);
basemult*=calculateRangerMultiplier(damager);
basemult*=calculatePotionEffectMultiplier(ent);
double mult = calculatePoisonEffectMultiplier(target);
addMultiplierToPlayerLogger(ent,"Poison Mult",mult);
basemult*=mult;
if (meleeWithBow(weapon,damager) && !useBow) {
basedmg = 2.0;
basemult = 1.0 * calculateEnchantmentDamageIncrease(weapon,damager,target);
performMegaKnockback(damager,target);
} else {
if (!useBow) {
basemult*=calculateBowDrawbackMultiplier(weapon,damager);
double headshot_mult = calculateHeadshotMultiplier(damager,weapon,target);
headshot = headshot_mult>1.0;
addMultiplierToPlayerLogger(damager,"Headshot Mult",headshot_mult);
basemult*=headshot_mult;
double arrow_mult = calculateArrowMultiplier(damager,weapon,target);
basemult*=arrow_mult;
//This is an arrow shot from a bow.
}
}
applyOnHitEffects(weapon,basedmg * basemult,damager,target,headshot);
} else {
if (damager instanceof Arrow) {
return 4.5; //This is a basic arrow with no shooter. Deal some damage.
} else {
return 1.0;
}
}
setPlayerTarget(damager,target,headshot,preemptive);
return basedmg * basemult;
}
private static double calculateArrowMultiplier(Entity damager, ItemStack weapon, LivingEntity target) {
double mult = 1.0;
LivingEntity shooter = getDamagerEntity(damager);
if (shooter instanceof Player) {
Player p = (Player)shooter;
if (damager instanceof TippedArrow) {
TippedArrow a = (TippedArrow)damager;
if (a.hasMetadata("DOUBLE_DAMAGE_ARR")) {
mult*=2.0;
addMultiplierToPlayerLogger(damager,"Handmade Arrow Mult",mult);
}
if (a.hasMetadata("QUADRUPLE_DAMAGE_ARR")) {
mult*=4.0;
addMultiplierToPlayerLogger(damager,"Diamond-Tipped Arrow Mult",mult);
}
}
}
return mult;
}
private static void setPlayerTarget(Entity damager, LivingEntity target, boolean headshot, boolean preemptive) {
LivingEntity shooter = getDamagerEntity(damager);
if (shooter instanceof Player) {
Player pl = (shooter instanceof Player)?(Player)shooter:(Player)target;
PlayerStructure pd = (PlayerStructure)TwosideKeeper.playerdata.get(pl.getUniqueId());
if (shooter instanceof Player) {
pd.target=getDamagerEntity(target);
}
pd.headshot=headshot;
pd.preemptive=preemptive;
if (pd.damagelogging) {
DecimalFormat df = new DecimalFormat("0.0");
//TwosideKeeper.updateTitle(pl,pd);
} else {
TwosideKeeper.updateTitle(pl,headshot,preemptive);
}
}
}
private static void performMegaKnockback(Entity damager,final LivingEntity target) {
if (damager instanceof Player) {
Player p = (Player)damager;
if (GenericFunctions.isRanger(p)) {
Bukkit.getScheduler().scheduleSyncDelayedTask(Bukkit.getPluginManager().getPlugin("TwosideKeeper"), new Runnable() {
public void run() {
if (target!=null) {
target.setVelocity(target.getVelocity().setY(0.1).multiply(8));
}
}}
,1);
}
}
}
private static double calculatePoisonEffectMultiplier(LivingEntity target) {
double mult = 1.0;
if (target!=null) {
mult += (GenericFunctions.getPotionEffectLevel(PotionEffectType.POISON, target)+1)*0.5;
mult += (GenericFunctions.getPotionEffectLevel(PotionEffectType.BLINDNESS, target)+1)*0.5;
}
return mult;
}
static double calculatePartyAttackMultiplier(Player p) {
int partylevel = 0;
PlayerStructure pd = PlayerStructure.GetPlayerStructure(p);
if (pd.partybonus>0) {
return 1.0+(pd.partybonus*0.1);
}
return 1.0;
}
static double getBaseArtifactDamageByType(ItemStack weapon) {
if (weapon.getType().toString().contains("SWORD")) {
return 3.0;
} else
if (weapon.getType().toString().contains("PICKAXE")) {
return 1.25;
} else
if (weapon.getType().toString().contains("PICKAXE")) {
return 1.25;
} else
if (weapon.getType().toString().contains("AXE")) {
return 4.0;
} else
if (weapon.getType().toString().contains("SPADE")) {
return 1.5;
} else
if (weapon.getType().toString().contains("BOW")) {
return 4.5;
}
return 1.0;
}
static double getBaseDamageByType(ItemStack weapon) {
switch (weapon.getType()) {
case WOOD_SWORD:{
return 3.0;
}
case STONE_SWORD:{
return 4.0;
}
case GOLD_SWORD:{
return 10.0;
}
case IRON_SWORD:{
return 7.0;
}
case DIAMOND_SWORD:{
return 9.0;
}
case WOOD_SPADE:{
return 1.5;
}
case STONE_SPADE:{
return 2.5;
}
case GOLD_SPADE:{
return 8.0;
}
case IRON_SPADE:{
return 5.0;
}
case DIAMOND_SPADE:{
return 7.0;
}
case WOOD_PICKAXE:{
return 1.25;
}
case STONE_PICKAXE:{
return 2.0;
}
case GOLD_PICKAXE:{
return 7.5;
}
case IRON_PICKAXE:{
return 4.5;
}
case DIAMOND_PICKAXE:{
return 6.0;
}
case WOOD_AXE:{
return 4.0;
}
case STONE_AXE:{
return 5.0;
}
case GOLD_AXE:{
return 11.0;
}
case IRON_AXE:{
return 8.0;
}
case DIAMOND_AXE:{
return 9.0;
}
case BOW:{
return 4.5;
}
default:{
return 1.0;
}
}
}
public static LivingEntity getDamagerEntity(Entity damager) {
return (damager instanceof LivingEntity)?((LivingEntity)damager):
((damager instanceof Projectile) && (((Projectile)damager).getShooter() instanceof LivingEntity))?(LivingEntity)((Projectile)damager).getShooter():null;
}
static double calculateEnchantmentDamageIncrease(ItemStack weapon, Entity damager, LivingEntity target) {
double dmg = 0.0;
boolean isBow = (weapon!=null && weapon.getType()==Material.BOW); //An exception for melee'ing with bows.
if (isBow && (damager instanceof Arrow)) {
double dmg1 = (weapon.containsEnchantment(Enchantment.ARROW_DAMAGE))?1.0+weapon.getEnchantmentLevel(Enchantment.ARROW_DAMAGE)*0.5:0.0;
addToPlayerLogger(damager,"POWER",dmg1);
dmg+=dmg1;
} else {
double mult1 = (weapon.containsEnchantment(Enchantment.DAMAGE_ALL))?1.0+weapon.getEnchantmentLevel(Enchantment.DAMAGE_ALL)*0.5:0.0;
addToPlayerLogger(damager,"SHARPNESS",mult1);
dmg+=mult1;
if (weapon.containsEnchantment(Enchantment.DAMAGE_ARTHROPODS) &&
(target instanceof Spider)) {
mult1 = 1.0+weapon.getEnchantmentLevel(Enchantment.DAMAGE_ARTHROPODS)*2.5;
addToPlayerLogger(damager,"BANE OF ARTHROPODS",mult1);
dmg+=mult1;
}
if (weapon.containsEnchantment(Enchantment.DAMAGE_UNDEAD) &&
(target instanceof Monster) && MonsterController.isUndead((Monster)target)) {
mult1 = 1.0+weapon.getEnchantmentLevel(Enchantment.DAMAGE_UNDEAD)*2.5;
addToPlayerLogger(damager,"SMITE",mult1);
dmg+=mult1;
}
}
return dmg;
}
static double calculateArtifactAbilityDamageIncrease(ItemStack weapon, Entity damager,
LivingEntity target) {
double dmg = 0.0;
double dmg1 = GenericFunctions.getAbilityValue(ArtifactAbility.DAMAGE,weapon);
addToPlayerLogger(damager,"Artifact Ability - DAMAGE",dmg1);
dmg+=dmg1;
dmg1 = calculateExecutionDamage(weapon,target);
addToPlayerLogger(damager,"Artifact Ability - EXECUTION",dmg1);
dmg+=dmg1;
dmg1 = calculateHighwinderDamage(weapon,damager);
addToPlayerLogger(damager,"Artifact Ability - HIGHWINDER",dmg1);
dmg+=dmg1;
return dmg;
}
private static double calculateHighwinderDamage(ItemStack weapon, Entity damager) {
double dmg = 0.0;
if (damager instanceof Player) {
Player p = (Player)damager;
PlayerStructure pd = PlayerStructure.GetPlayerStructure(p);
dmg += 93.182445*pd.velocity*GenericFunctions.getAbilityValue(ArtifactAbility.HIGHWINDER, weapon);
}
return dmg;
}
static double calculateExecutionDamage(ItemStack weapon, LivingEntity target) {
if (target!=null) {
return getPercentHealthMissing(target)
/20
*GenericFunctions.getAbilityValue(ArtifactAbility.EXECUTION,weapon);
}
return 0.0;
}
//Returns between 0-100.
static double getPercentHealthRemaining(LivingEntity target) {
return ((target.getHealth()/target.getMaxHealth())*100);
}
static double getPercentHealthMissing(LivingEntity target) {
return 100-getPercentHealthRemaining(target);
}
static double calculateArtifactAbilityMultiplier(ItemStack weapon, Entity damager, LivingEntity target) {
double mult = 1.0;
double mult1 = calculateBeliggerentMultiplier(weapon,damager);
addMultiplierToPlayerLogger(damager,"Belliggerent Mult",mult1);
mult*=mult1;
return mult;
}
static double calculatePlayerCriticalStrike(ItemStack weapon, Entity damager) {
boolean criticalstrike=false;
double critchance = 0.0;
critchance += calculateCriticalStrikeChance(weapon, damager);
TwosideKeeper.log("Crit Strike chance is "+critchance,4);
criticalstrike = isCriticalStrike(critchance);
if (damager instanceof Player && criticalstrike) {
Player p = (Player)damager;
p.playSound(p.getLocation(), Sound.ENTITY_PLAYER_ATTACK_CRIT, 1.0f, 1.0f);
}
return criticalstrike?(calculateCriticalStrikeMultiplier(weapon)):1.0;
}
static double calculateCriticalStrikeChance(ItemStack weapon, Entity damager) {
double critchance = 0.0;
critchance += 0.01*GenericFunctions.getAbilityValue(ArtifactAbility.CRITICAL,weapon);
LivingEntity shooter = getDamagerEntity(damager);
if (shooter!=null) {
if (shooter instanceof Player) {
Player p = (Player)shooter;
critchance += (GenericFunctions.isStriker(p)?0.2:0.0);
critchance += ItemSet.TotalBaseAmountBasedOnSetBonusCount(p,ItemSet.PANROS,4,4)/100d;
critchance += (GenericFunctions.isRanger(p)?(GenericFunctions.getPotionEffectLevel(PotionEffectType.SLOW, p)+1)*0.1:0.0);
}
}
return critchance;
}
//Chance is between 0.0-1.0. 1.0 is 100%.
static boolean isCriticalStrike(double chance) {
return (Math.random()<=chance);
}
static double calculateCriticalStrikeMultiplier(ItemStack weapon) {
double critdmg=2.0;
if (ArtifactAbility.containsEnchantment(ArtifactAbility.CRIT_DMG, weapon)) {
critdmg+=(GenericFunctions.getAbilityValue(ArtifactAbility.CRIT_DMG,weapon)-200)/100d;
}
return critdmg;
}
static double calculateBeliggerentMultiplier(ItemStack weapon, Entity damager) {
double mult=1.0;
if (damager instanceof Player) {
Player p = (Player)damager;
PlayerStructure pd = PlayerStructure.GetPlayerStructure(p);
mult+=pd.swordcombo*GenericFunctions.getAbilityValue(ArtifactAbility.COMBO, weapon)/100d;
}
return mult;
}
static double calculateStrikerMultiplier(Entity damager) {
double mult=1.0;
if (damager instanceof Player) {
Player p = (Player)damager;
if (GenericFunctions.isStriker(p)) {
double mult1 = (1-(p.getHealth()/p.getMaxHealth()));
addMultiplierToPlayerLogger(damager,"Striker Missing Health Mult",mult1);
mult += mult1;
mult1 = 0.10;
addMultiplierToPlayerLogger(damager,"Striker Passive Mult",mult1);
mult += mult1; //10% damage increase - striker passive.
}
}
return mult;
}
static double calculateRangerMultiplier(Entity damager) {
double mult=1.0;
LivingEntity shooter = getDamagerEntity(damager);
if (shooter instanceof Player) {
Player p = (Player)shooter;
if (GenericFunctions.isRanger(p)) {
double mult1 = 4.0;
addMultiplierToPlayerLogger(damager,"Ranger Passive Mult",mult1);
mult *= mult1; //x4 damage - Ranger passive.
}
}
return mult;
}
static double calculatePotionEffectMultiplier(LivingEntity damager) {
double mult = 1.0;
double mult1 = 1.0+(GenericFunctions.getPotionEffectLevel(PotionEffectType.INCREASE_DAMAGE, damager)+1)*0.1;
addMultiplierToPlayerLogger(damager,"STRENGTH Mult",mult1);
mult *= mult1;
int weaknesslv = Math.abs(GenericFunctions.getPotionEffectLevel(PotionEffectType.WEAKNESS, damager))+1;
if (weaknesslv<=10) {
mult1 = 1.0-(weaknesslv*0.1);
addMultiplierToPlayerLogger(damager,ChatColor.RED+"WEAKNESS Mult",mult1);
mult *= 1.0-(weaknesslv*0.1);
} else {
addMultiplierToPlayerLogger(damager,ChatColor.RED+"WEAKNESS Mult",0.0);
mult = 0.0;
}
return mult;
}
static boolean meleeWithBow(ItemStack weapon, Entity damager) {
if (weapon!=null &&
weapon.getType()==Material.BOW &&
(damager instanceof Player)) {
//That means this player melee'd with a bow.
TwosideKeeper.log("Melee with bow",5);
return true;
} else {
return false;
}
}
static double calculateBowDrawbackMultiplier(ItemStack weapon, Entity damager) {
double mult=1.0;
LivingEntity shooter = getDamagerEntity(damager);
if (weapon.getType()==Material.BOW &&
shooter instanceof Player) {
Player p = (Player)shooter;
PlayerStructure pd = PlayerStructure.GetPlayerStructure(p);
double mult1 = (pd.lastarrowwasinrangermode)?(pd.lastarrowpower/9000000d):(pd.lastarrowpower/9d);
addMultiplierToPlayerLogger(damager,"Base Arrow Damage Mult",mult1);
mult = mult1;
}
TwosideKeeper.log("mult is "+mult,5);
return mult;
}
private static void applyOnHitEffects(ItemStack weapon, double dmg, Entity damager, LivingEntity target) {
applyOnHitEffects(weapon,dmg,damager,target,false);
}
static void applyOnHitEffects(ItemStack weapon, double dmg, Entity damager, LivingEntity target, boolean headshot) {
LivingEntity shooter = getDamagerEntity(damager);
if ((shooter instanceof Player) && target!=null) {
Player p = (Player)shooter;
if (damager instanceof TippedArrow) {
TippedArrow a = (TippedArrow)damager;
if (a.hasMetadata("EXPLODE_ARR")) {
//Create an explosion.
TwosideKeeper.log("In here", 5);
Location hitloc = aPlugin.API.getArrowHitLocation(target, a);
GenericFunctions.DealExplosionDamageToEntities(hitloc, NewCombat.CalculateWeaponDamage(p,null)+40, 6);
p.playSound(hitloc, Sound.ENTITY_ENDERDRAGON_FIREBALL_EXPLODE, 0.5f, 1.0f);
aPlugin.API.sendSoundlessExplosion(hitloc, 2);
}
if (a.hasMetadata("TRAP_ARR")) {
int slownesslv=0;
if (target.hasPotionEffect(PotionEffectType.SLOW)) {
slownesslv = GenericFunctions.getPotionEffectLevel(PotionEffectType.SLOW, target)+1;
target.removePotionEffect(PotionEffectType.SLOW);
}
target.addPotionEffect(new PotionEffect(PotionEffectType.SLOW,20*5,slownesslv));
}
if (a.hasMetadata("POISON_ARR")) {
int poisonlv=0;
target.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS,20*20,0));
}
}
if (GenericFunctions.isArtifactEquip(p.getEquipment().getItemInMainHand()) &&
GenericFunctions.isArtifactWeapon(p.getEquipment().getItemInMainHand())) {
double ratio = 1.0-CalculateDamageReduction(1,target,p);
AwakenedArtifact.addPotentialEXP(p.getEquipment().getItemInMainHand(), (int)((ratio*20)+5)*((headshot)?2:1), p);
increaseArtifactArmorXP(p,(int)(ratio*10)+1);
List<LivingEntity> hitlist = getAOEList(weapon,target);
boolean applyDeathMark=false;
if (ArtifactAbility.getEnchantmentLevel(ArtifactAbility.DEATHMARK, p.getEquipment().getItemInMainHand())>0) {
applyDeathMark=true;
}
for (int i=0;i<hitlist.size();i++) {
if (!hitlist.get(i).equals(target)) {
//hitlist.get(i).damage(dmg);
GenericFunctions.DealDamageToMob(CalculateDamageReduction(dmg,target,damager), hitlist.get(i), shooter, weapon, "AoE Damage");
};
if (applyDeathMark) {
GenericFunctions.ApplyDeathMark(hitlist.get(i));
}
}
final List<LivingEntity> finallist = hitlist;
Bukkit.getScheduler().scheduleSyncDelayedTask(Bukkit.getPluginManager().getPlugin("TwosideKeeper"), new Runnable() {
public void run() {
for (int i=0;i<finallist.size();i++) {
LivingEntity le = finallist.get(i);
if (le!=null && !le.isDead() && !le.hasPotionEffect(PotionEffectType.UNLUCK)) {
GenericFunctions.ResetMobName(le);
//They don't have death marks anymore, so we just remove their name color.
}
}
}}
,100);
healDefenderSaturation(p);
increaseSwordComboCount(weapon, p);
}
}
}
private static void healDefenderSaturation(Player p) {
if (GenericFunctions.isDefender(p) && p.getSaturation()<20) {
p.setSaturation(p.getSaturation()+1);
}
}
public static void increaseArtifactArmorXP(Player p, int exp) {
for (int i=0;i<p.getEquipment().getArmorContents().length;i++) {
if (GenericFunctions.isArtifactEquip(p.getEquipment().getArmorContents()[i]) &&
GenericFunctions.isArtifactArmor(p.getEquipment().getArmorContents()[i])) {
AwakenedArtifact.addPotentialEXP(p.getEquipment().getArmorContents()[i], exp, p);
}
}
}
static void increaseSwordComboCount(ItemStack weapon, Player p) {
if (ArtifactAbility.containsEnchantment(ArtifactAbility.COMBO, p.getEquipment().getItemInMainHand())) {
PlayerStructure pd = PlayerStructure.GetPlayerStructure(p);
if (pd.last_swordhit+40>=TwosideKeeper.getServerTickTime()) {
pd.last_swordhit=TwosideKeeper.getServerTickTime();
pd.swordcombo++;
} else {
pd.last_swordhit=TwosideKeeper.getServerTickTime();
pd.swordcombo=1;
}
}
}
static List<LivingEntity> getAOEList(ItemStack weapon, LivingEntity target) {
List<LivingEntity> list = new ArrayList<LivingEntity>();
if (ArtifactAbility.containsEnchantment(ArtifactAbility.AOE, weapon)) {
double aoerange = GenericFunctions.getAbilityValue(ArtifactAbility.AOE, weapon);
if (target!=null) {
List<Entity> nearbylist=target.getNearbyEntities(aoerange,aoerange,aoerange);
list = trimNonLivingEntities(nearbylist);
//list.remove(target);
}
}
list.add(target);
return list;
}
public static List<LivingEntity> trimNonLivingEntities(List<Entity> entitylist) {
List<LivingEntity> livinglist = new ArrayList<LivingEntity>();
for (int i=0;i<entitylist.size();i++) {
if ((entitylist.get(i) instanceof LivingEntity) && !(entitylist.get(i) instanceof Player)) {
livinglist.add((LivingEntity)entitylist.get(i));
}
}
return livinglist;
}
public static List<Monster> trimNonMonsterEntities(List<Entity> entitylist) {
List<Monster> livinglist = new ArrayList<Monster>();
for (int i=0;i<entitylist.size();i++) {
if ((entitylist.get(i) instanceof Monster) && !(entitylist.get(i) instanceof Player)) {
livinglist.add((Monster)entitylist.get(i));
}
}
return livinglist;
}
static public double CalculateDamageReduction(double basedmg,LivingEntity target,Entity damager) {
double dmgreduction = 0.0;
int protectionlevel = 0;
int resistlevel = 0;
int partylevel = 0;
if (target instanceof LivingEntity) {
ItemStack[] armor = target.getEquipment().getArmorContents();
if (target instanceof Player) {
if (GenericFunctions.HasFullRangerSet((Player)target)) {
dmgreduction+=20.0;
}
}
for (int i=0;i<armor.length;i++) {
if (armor[i]!=null) {
//Check for Protection enchantment.
//Each Protection level gives 1% extra damage reduction.
if (armor[i].getEnchantmentLevel(Enchantment.PROTECTION_ENVIRONMENTAL)>0) {
protectionlevel+=armor[i].getEnchantmentLevel(Enchantment.PROTECTION_ENVIRONMENTAL);
}
if ((damager instanceof Projectile) && armor[i].getEnchantmentLevel(Enchantment.PROTECTION_PROJECTILE)>0) {
protectionlevel+=armor[i].getEnchantmentLevel(Enchantment.PROTECTION_PROJECTILE);
}
if ((damager instanceof Creeper) && armor[i].getEnchantmentLevel(Enchantment.PROTECTION_EXPLOSIONS)>0) {
protectionlevel+=armor[i].getEnchantmentLevel(Enchantment.PROTECTION_EXPLOSIONS);
}
boolean isBlockArmor = GenericFunctions.isHardenedItem(armor[i]);
if (target instanceof Monster) {
isBlockArmor=true;
}
//If this is an artifact armor, we totally override the base damage reduction.
if (GenericFunctions.isArmor(armor[i]) && Artifact.isArtifact(armor[i])) {
//Let's change up the damage.
//double dmgval = ArtifactItemType.valueOf(Artifact.returnRawTool(armor[i].getType())).getDamageAmt(armor[i].getEnchantmentLevel(Enchantment.LUCK));
double dmgval=-1;
if (dmgval!=-1) {
dmgreduction += dmgval;
}
} else {
switch (armor[i].getType()) {
case LEATHER_BOOTS:
case LEATHER_LEGGINGS:
case LEATHER_CHESTPLATE:
case LEATHER_HELMET: {
dmgreduction+=3*((isBlockArmor)?2:1);
}break;
case IRON_BOOTS:
case IRON_LEGGINGS:
case IRON_CHESTPLATE:
case IRON_HELMET: {
dmgreduction+=5*((isBlockArmor)?2:1);
}break;
case GOLD_BOOTS:
case GOLD_LEGGINGS:
case GOLD_CHESTPLATE:
case GOLD_HELMET: {
dmgreduction+=10*((isBlockArmor)?2:1);
}break;
case DIAMOND_BOOTS:
case DIAMOND_LEGGINGS:
case DIAMOND_CHESTPLATE:
case DIAMOND_HELMET: {
dmgreduction+=8*((isBlockArmor)?2:1);
}break;
}
}
if (GenericFunctions.isArtifactEquip(armor[i])) {
double reductionamt = GenericFunctions.getAbilityValue(ArtifactAbility.DAMAGE_REDUCTION, armor[i]);
dmgreduction+=reductionamt;
TwosideKeeper.log("Reducing damage by "+reductionamt+"%",5);
/*if (ArtifactAbility.containsEnchantment(ArtifactAbility.GREED, armor[i])) {
dmgreduction /= ArtifactAbility.containsEnchantment(ArtifactAbility.GREED, armor[i])?2:1;
}*/
}
}
}
//Check for resistance effect.
Collection<PotionEffect> target_effects = target.getActivePotionEffects();
for (int i=0;i<target_effects.size();i++) {
if (Iterables.get(target_effects, i).getType().equals(PotionEffectType.DAMAGE_RESISTANCE)) {
resistlevel = Iterables.get(target_effects, i).getAmplifier()+1;
TwosideKeeper.log("Resistance level is "+resistlevel,5);
}
}
}
double setbonus = 1.0;
if (target instanceof Player) {
Player p = (Player)target;
PlayerStructure pd = PlayerStructure.GetPlayerStructure(p);
partylevel = pd.partybonus;
if (partylevel>9) {partylevel=9;}
if (p.getLocation().getY()>=0) {TwosideKeeper.log("Light level: "+p.getLocation().add(0,0,0).getBlock().getLightLevel(),5);}
for (int i=0;i<p.getEquipment().getArmorContents().length;i++) {
if (ArtifactAbility.containsEnchantment(ArtifactAbility.SHADOWWALKER, p.getEquipment().getArmorContents()[i]) &&
p.getLocation().getY()>=0 &&
p.isOnGround() && p.getLocation().add(0,0,0).getBlock().getLightLevel()<=4) {
double dmgreduce = 1d-(GenericFunctions.getAbilityValue(ArtifactAbility.SHADOWWALKER, p.getEquipment().getArmorContents()[i])/100d);
basedmg *= dmgreduce;
TwosideKeeper.log("Base damage became "+(dmgreduce*100)+"% of original amount.",5);
}
if (ArtifactAbility.containsEnchantment(ArtifactAbility.GREED, p.getEquipment().getArmorContents()[i])) {
dmgreduction /= ArtifactAbility.containsEnchantment(ArtifactAbility.GREED, p.getEquipment().getArmorContents()[i])?2:1;
}
}
if (ArtifactAbility.containsEnchantment(ArtifactAbility.GREED, p.getEquipment().getItemInMainHand())) {
dmgreduction /= ArtifactAbility.containsEnchantment(ArtifactAbility.GREED, p.getEquipment().getItemInMainHand())?2:1;
}
setbonus = ((100-ItemSet.TotalBaseAmountBasedOnSetBonusCount(p, ItemSet.SONGSTEEL, 4, 4))/100d);
}
//Blocking: -((p.isBlocking())?ev.getDamage()*0.33:0) //33% damage will be reduced if we are blocking.
//Shield: -((p.getEquipment().getItemInOffHand()!=null && p.getEquipment().getItemInOffHand().getType()==Material.SHIELD)?ev.getDamage()*0.05:0) //5% damage will be reduced if we are holding a shield.
TwosideKeeper.log("Protection level: "+protectionlevel, 5);
resistlevel=(resistlevel>10)?10:resistlevel;
protectionlevel=(protectionlevel>100)?100:protectionlevel;
partylevel=(partylevel>100)?100:partylevel;
double finaldmg=(basedmg-(basedmg*(dmgreduction/100.0d)))
*((10-resistlevel)*0.1)
*((100-protectionlevel)*0.01)
*((10-partylevel)*0.1)
*setbonus
*((target instanceof Player && ((Player)target).isBlocking())?(GenericFunctions.isDefender((Player)target))?0.30:0.50:1)
*((target instanceof Player)?((GenericFunctions.isDefender((Player)target))?0.9:(target.getEquipment().getItemInOffHand()!=null && target.getEquipment().getItemInOffHand().getType()==Material.SHIELD)?0.95:1):1);
if (basedmg!=finaldmg) {
TwosideKeeper.log("Original damage was: "+basedmg,5);
TwosideKeeper.log(finaldmg+" damage calculated for: "+target.getName()+".",5);
}
if (damager instanceof Player) {
Player p = (Player)damager;
double lifestealpct = calculateLifeStealAmount(p);
double healamt = finaldmg*lifestealpct;
//log("Healed "+healamt+" damage.",2);
double newhealth = p.getHealth()+healamt;
if (newhealth>p.getMaxHealth()) {
p.setMaxHealth(p.getMaxHealth());
} else {
p.setHealth(newhealth);
}
}
if (target instanceof Player) {
Player p = (Player)target;
PlayerStructure pd = PlayerStructure.GetPlayerStructure(p);
pd.prev_armordef = finaldmg;
}
return finaldmg;
}
public static double calculateLifeStealAmount(Player p) {
double lifestealpct = GenericFunctions.getAbilityValue(ArtifactAbility.LIFESTEAL, p.getEquipment().getItemInMainHand())/100;
for (int i=0;i<GenericFunctions.getEquipment(p).length;i++) {
ItemSet set = ItemSet.GetSet(GenericFunctions.getEquipment(p)[i]);
if (set!=null) {
if (set==ItemSet.DAWNTRACKER) {
lifestealpct += set.GetBaseAmount(GenericFunctions.getEquipment(p)[i])/100d;
}
}
}
lifestealpct += ItemSet.TotalBaseAmountBasedOnSetBonusCount(p, ItemSet.DAWNTRACKER, 3, 3)/100d;
return lifestealpct;
}
private static void playerAddArtifactEXP(LivingEntity target, double dmg) {
if (target instanceof Player) {
Player p = (Player)target;
increaseArtifactArmorXP(p,(int)dmg);
}
}
private static double calculateHeadshotMultiplier(Entity arrow, ItemStack weapon, LivingEntity target) {
double mult = 1.0;
if (target instanceof Monster &&
arrow instanceof Projectile) {
//Headshot conditions:
/*
* If Target is WEARING Helmet:
* ->Direction difference has to be anywhere between 110-250 degrees.
*
* In Addition, for ALL targets:
* ->Y must be greater than or equal to Eye Height - 0.22f .
* ->Perks or abilities with increased headshot hitbox size will multiply the 0.08 further, giving
* more access to the target's body.
*/
Monster m = (Monster)target;
Projectile proj = (Projectile)arrow;
Location arrowLoc = proj.getLocation();
if (proj instanceof Arrow) {
arrowLoc = aPlugin.API.getArrowHitLocation(target, (Arrow)proj);
}
Location monsterHead = m.getEyeLocation();
TwosideKeeper.log("Distance: "+(arrowLoc.distanceSquared(monsterHead)), 3);
double headshotvaly=0.22/TwosideKeeper.HEADSHOT_ACC;
double directionvaly=0.25/TwosideKeeper.HEADSHOT_ACC;
if (proj.getShooter() instanceof Player) {
Player p = (Player)proj.getShooter();
if (GenericFunctions.isRanger(p) &&
GenericFunctions.getBowMode(weapon)==BowMode.SNIPE) {
aPlugin.API.sendSoundlessExplosion(arrowLoc, 1);
headshotvaly *= 4;
}
if (GenericFunctions.isArtifactEquip(weapon) &&
ArtifactAbility.containsEnchantment(ArtifactAbility.MARKSMAN, weapon)) {
headshotvaly *= 1+(GenericFunctions.getAbilityValue(ArtifactAbility.MARKSMAN, weapon)/100d);
}
if (proj.getTicksLived()>=4 || GenericFunctions.isRanger(p)) {
if (arrowLoc.distanceSquared(monsterHead)<=0.3*headshotvaly) {
PlayerStructure pd = PlayerStructure.GetPlayerStructure(p);
if (GenericFunctions.isRanger(p) && GenericFunctions.getBowMode(p.getEquipment().getItemInMainHand())==BowMode.SNIPE) {
if (pd.headshotcombo<8) {pd.headshotcombo++;}
double headshotincrease = (2+(pd.headshotcombo*0.25));
mult*=headshotincrease;
p.sendMessage(ChatColor.DARK_RED+"Headshot! x"+(headshotincrease)+" Damage");
if (p.hasPotionEffect(PotionEffectType.SLOW)) {
//Add to the current stack of SLOW.
for (int i1=0;i1<p.getActivePotionEffects().size();i1++) {
if (Iterables.get(p.getActivePotionEffects(), i1).getType().equals(PotionEffectType.SLOW)) {
int lv = Iterables.get(p.getActivePotionEffects(), i1).getAmplifier();
TwosideKeeper.log("New Slowness level: "+lv,5);
p.removePotionEffect(PotionEffectType.SLOW);
p.addPotionEffect(new PotionEffect(PotionEffectType.SLOW,99,lv+1));
p.removePotionEffect(PotionEffectType.DAMAGE_RESISTANCE);
p.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE,99,lv+1));
break;
}
}
} else {
p.removePotionEffect(PotionEffectType.SLOW);
p.addPotionEffect(new PotionEffect(PotionEffectType.SLOW,99,0));
p.removePotionEffect(PotionEffectType.DAMAGE_RESISTANCE);
p.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE,99,0));
}
final Player pl = p;
Bukkit.getScheduler().scheduleSyncDelayedTask(Bukkit.getPluginManager().getPlugin("TwosideKeeper"), new Runnable() {
public void run() {
if (pl!=null && pl.isOnline() && !pl.hasPotionEffect(PotionEffectType.SLOW)) {
PlayerStructure pd = (PlayerStructure)TwosideKeeper.playerdata.get(pl.getUniqueId());
pd.headshotcombo=0;
}
}}
,100);
p.playSound(p.getLocation(), Sound.ENTITY_LIGHTNING_IMPACT, 0.1f, 0.24f);
} else {
mult*=2.0;
p.sendMessage(ChatColor.DARK_RED+"Headshot! x2 Damage");
if (GenericFunctions.isRanger(p) && GenericFunctions.getBowMode(p.getEquipment().getItemInMainHand())==BowMode.DEBILITATION) {
if (m.hasPotionEffect(PotionEffectType.BLINDNESS)) {
//Add to the current stack of BLINDNESS.
for (int i1=0;i1<m.getActivePotionEffects().size();i1++) {
if (Iterables.get(m.getActivePotionEffects(), i1).getType().equals(PotionEffectType.BLINDNESS)) {
int lv = Iterables.get(m.getActivePotionEffects(), i1).getAmplifier();
TwosideKeeper.log("New BLINDNESS level: "+lv,5);
p.playSound(p.getLocation(), Sound.ENTITY_RABBIT_ATTACK, 0.1f, 0.1f+((lv+1)*0.5f));
m.removePotionEffect(PotionEffectType.BLINDNESS);
m.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS,400,lv+1));
break;
}
}
} else {
m.removePotionEffect(PotionEffectType.BLINDNESS);
m.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS,400,0));
p.playSound(p.getLocation(), Sound.ENTITY_RABBIT_ATTACK, 0.1f, 0.1f);
}
}
}
}
}
}
}
return mult;
}
private static boolean arrowWithinHelmetBounds(Location arrowLoc, Monster m, double direction_acc) {
double dir_diff = (arrowLoc.getDirection().setX(0.0).setZ(0.0)).subtract((m.getLocation().getDirection().setX(0.0).setZ(0.0))).getY();
TwosideKeeper.log("Directional difference: "+dir_diff,4);
if (dir_diff<=direction_acc || m.getEquipment().getHelmet()==null || !m.getEquipment().getHelmet().getType().toString().contains("HELMET")) {
return true;
}
return false;
}
private static boolean arrowWithinYBounds(Location arrowLoc,Location monsterHead,double headshot_acc) {
TwosideKeeper.log("Y diff is "+(arrowLoc.getY()-monsterHead.getY()), 4);
return Math.abs(arrowLoc.getY()-monsterHead.getY())<=headshot_acc || arrowLoc.getY()>monsterHead.getY();
}
private static void applyOnHitMobEffects(LivingEntity target, Entity damager, double dmg) {
if (target instanceof Player) {
Player p = (Player)target;
if (GenericFunctions.isDefender(p)) {
int resistlevel = GenericFunctions.getPotionEffectLevel(PotionEffectType.DAMAGE_RESISTANCE, p);
if (resistlevel<4) {
p.removePotionEffect(PotionEffectType.DAMAGE_RESISTANCE);
p.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE,100,resistlevel+1));
} else {
p.removePotionEffect(PotionEffectType.DAMAGE_RESISTANCE);
p.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE,100,resistlevel));
}
if (p.isBlocking() && ItemSet.hasFullSet(p, ItemSet.SONGSTEEL)) {
PlayerStructure pd = PlayerStructure.GetPlayerStructure(p);
pd.vendetta_amt+=(dmg-CalculateDamageReduction(dmg,target,damager))*0.3;
aPlugin.API.sendActionBarMessage(p, ChatColor.YELLOW+"Vendetta: "+ChatColor.GREEN+Math.round(pd.vendetta_amt)+" dmg stored");
}
}
if (damager instanceof Enderman) {
if (MonsterController.getMonsterDifficulty(((Monster)damager))==MonsterDifficulty.HELLFIRE) {
for (int i=0;i<4;i++) {
if (Math.random()<=0.2) {
Monster mm = MonsterController.spawnAdjustedMonster(MonsterType.ENDERMITE, damager.getLocation().add(0,1,0));
mm.addPotionEffect(new PotionEffect(PotionEffectType.SPEED,Integer.MAX_VALUE,2));
}
}
}
}
}
}
public static void addToPlayerLogger(Entity p, String event, double val) {
LivingEntity l = getDamagerEntity(p);
if (l!=null && l instanceof Player) {
PlayerStructure pd = PlayerStructure.GetPlayerStructure((Player)l);
if (pd.damagelogging) {
pd.damagedata.addEventToLogger(event, val);
}
}
}
public static void addToLoggerTotal(Entity p, double val) {
LivingEntity l = getDamagerEntity(p);
if (l!=null && l instanceof Player) {
PlayerStructure pd = PlayerStructure.GetPlayerStructure((Player)l);
if (pd.damagelogging) {
pd.damagedata.addCalculatedActualDamage(val);
pd.damagedata.addCalculatedTotalDamage(val);
}
}
}
private static void addMultiplierToPlayerLogger(Entity p, String event, double val) {
LivingEntity l = getDamagerEntity(p);
if (l!=null && l instanceof Player) {
PlayerStructure pd = PlayerStructure.GetPlayerStructure((Player)l);
if (pd.damagelogging) {
pd.damagedata.addMultiplierToLogger(event, val);
}
}
}
public static double calculateAbsorptionHearts(LivingEntity target, double finaldmg) {
if (target.hasPotionEffect(PotionEffectType.ABSORPTION)) {
int abslv = GenericFunctions.getPotionEffectLevel(PotionEffectType.ABSORPTION, target)+1;
double healthabs = abslv*4; //The amount of health absorbed per level.
if (DamageIsSmallerThanAbsorptionAmount(finaldmg,healthabs)) {
SubtractDamageFromAbsorption(target, finaldmg,healthabs);
return 0.0; //Final damage becomes 0.
} else {
SubtractDamageFromAbsorption(target, finaldmg,healthabs);
return finaldmg-healthabs;
}
}
TwosideKeeper.log("New final damage is "+finaldmg, 4);
return finaldmg;
}
private static void SubtractDamageFromAbsorption(LivingEntity target, double finaldmg, double healthabs) {
int lvsToRemove = (int)(finaldmg/4);
if (finaldmg % 4 > 0) {
lvsToRemove++;
}
RemoveAbsorptionLevels(target,2);
}
private static void RemoveAbsorptionLevels(LivingEntity target, int amountOfAbsorptionLevels) {
int duration = GenericFunctions.getPotionEffectDuration(PotionEffectType.ABSORPTION, target);
int lv = GenericFunctions.getPotionEffectLevel(PotionEffectType.ABSORPTION, target);
target.removePotionEffect(PotionEffectType.ABSORPTION);
if (amountOfAbsorptionLevels<lv) {
target.addPotionEffect(new PotionEffect(PotionEffectType.ABSORPTION,duration,lv-amountOfAbsorptionLevels));
}
}
private static boolean DamageIsSmallerThanAbsorptionAmount(double finaldmg, double healthabs) {
return finaldmg<=healthabs;
}
public static double CalculateDodgeChance(Player p) {
double dodgechance = 0.0d;
dodgechance+=(ArtifactAbility.calculateValue(ArtifactAbility.DODGE, p.getEquipment().getItemInMainHand().getEnchantmentLevel(Enchantment.LUCK), ArtifactAbility.getEnchantmentLevel(ArtifactAbility.DODGE, p.getEquipment().getItemInMainHand()))/100d);
for (int i=0;i<p.getEquipment().getArmorContents().length;i++) {
if (ArtifactAbility.containsEnchantment(ArtifactAbility.SHADOWWALKER, p.getEquipment().getArmorContents()[i]) &&
p.isOnGround() && p.getLocation().getY()>=0 && p.getLocation().add(0,0,0).getBlock().getLightLevel()<=4) {
dodgechance+=0.01*p.getEquipment().getArmorContents()[i].getEnchantmentLevel(Enchantment.LUCK);
}
ItemStack equip = p.getEquipment().getArmorContents()[i];
if (GenericFunctions.isRanger(p) && equip!=null
&& equip.getType()!=Material.AIR &&
equip.hasItemMeta() && equip.getItemMeta().hasLore()) {
if (equip.getItemMeta().getLore().contains(ChatColor.GOLD+""+ChatColor.BOLD+"Jamdak Set")) {
dodgechance+=0.03;
} else
if (equip.getItemMeta().getLore().contains(ChatColor.GOLD+""+ChatColor.BOLD+"Darnys Set")) {
dodgechance+=0.05;
} else
if (equip.getItemMeta().getLore().contains(ChatColor.GOLD+""+ChatColor.BOLD+"Alikahn Set")) {
dodgechance+=0.08;
} else
if (equip.getItemMeta().getLore().contains(ChatColor.GOLD+""+ChatColor.BOLD+"Lorasaadi Set")) {
dodgechance+=0.11;
}
}
}
PlayerStructure pd = PlayerStructure.GetPlayerStructure(p);
if (ArtifactAbility.containsEnchantment(ArtifactAbility.SHADOWWALKER, p.getEquipment().getItemInMainHand()) &&
p.isOnGround() && p.getLocation().getY()>=0 && p.getLocation().add(0,0,0).getBlock().getLightLevel()<=4) {
dodgechance+=0.01*p.getEquipment().getItemInMainHand().getEnchantmentLevel(Enchantment.LUCK);
}
dodgechance+=ItemSet.TotalBaseAmountBasedOnSetBonusCount(p,ItemSet.PANROS,3,3)/100d;
if (GenericFunctions.isStriker(p) &&
pd.velocity>0) {
dodgechance+=0.2;
}
if (GenericFunctions.isRanger(p)) {
dodgechance+=0.5;
}
if (pd.fulldodge) {
dodgechance = 1.0;
}
return dodgechance;
}
}