CombatUtils.java 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844
  1. package com.gmail.nossr50.util.skills;
  2. import com.gmail.nossr50.core.MetadataConstants;
  3. import com.gmail.nossr50.datatypes.experience.SpecialXPKey;
  4. import com.gmail.nossr50.datatypes.experience.XPGainReason;
  5. import com.gmail.nossr50.datatypes.interactions.NotificationType;
  6. import com.gmail.nossr50.datatypes.meta.OldName;
  7. import com.gmail.nossr50.datatypes.player.McMMOPlayer;
  8. import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
  9. import com.gmail.nossr50.datatypes.skills.SubSkillType;
  10. import com.gmail.nossr50.events.fake.FakeEntityDamageByEntityEvent;
  11. import com.gmail.nossr50.events.fake.FakeEntityDamageEvent;
  12. import com.gmail.nossr50.mcMMO;
  13. import com.gmail.nossr50.party.PartyManager;
  14. import com.gmail.nossr50.runnables.skills.AwardCombatXpTask;
  15. import com.gmail.nossr50.skills.acrobatics.AcrobaticsManager;
  16. import com.gmail.nossr50.skills.archery.ArcheryManager;
  17. import com.gmail.nossr50.skills.axes.AxesManager;
  18. import com.gmail.nossr50.skills.swords.SwordsManager;
  19. import com.gmail.nossr50.skills.taming.TamingManager;
  20. import com.gmail.nossr50.skills.unarmed.Unarmed;
  21. import com.gmail.nossr50.skills.unarmed.UnarmedManager;
  22. import com.gmail.nossr50.util.*;
  23. import com.gmail.nossr50.util.player.NotificationManager;
  24. import com.gmail.nossr50.util.player.UserManager;
  25. import com.google.common.collect.ImmutableMap;
  26. import org.bukkit.GameMode;
  27. import org.bukkit.Material;
  28. import org.bukkit.entity.*;
  29. import org.bukkit.event.entity.EntityDamageByEntityEvent;
  30. import org.bukkit.event.entity.EntityDamageEvent;
  31. import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
  32. import org.bukkit.event.entity.EntityDamageEvent.DamageModifier;
  33. import org.bukkit.inventory.ItemStack;
  34. import org.bukkit.metadata.MetadataValue;
  35. import org.bukkit.projectiles.ProjectileSource;
  36. import java.util.EnumMap;
  37. import java.util.HashMap;
  38. import java.util.List;
  39. import java.util.Map;
  40. public final class CombatUtils {
  41. private CombatUtils() {
  42. }
  43. private static void processSwordCombat(LivingEntity target, Player player, EntityDamageByEntityEvent event) {
  44. if (event.getCause() == DamageCause.THORNS) {
  45. return;
  46. }
  47. McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
  48. SwordsManager swordsManager = mcMMOPlayer.getSwordsManager();
  49. double initialDamage = event.getDamage();
  50. double finalDamage = initialDamage;
  51. Map<DamageModifier, Double> modifiers = getModifiers(event);
  52. if (swordsManager.canActivateAbility()) {
  53. mcMMOPlayer.checkAbilityActivation(PrimarySkillType.SWORDS);
  54. }
  55. if (target.getHealth() - event.getFinalDamage() >= 1) {
  56. if (swordsManager.canUseRupture()) {
  57. swordsManager.ruptureCheck(target);
  58. }
  59. }
  60. //Add Stab Damage
  61. if (swordsManager.canUseStab()) {
  62. finalDamage += swordsManager.getStabDamage();
  63. }
  64. if (swordsManager.canUseSerratedStrike()) {
  65. swordsManager.serratedStrikes(target, initialDamage, modifiers);
  66. }
  67. if (canUseLimitBreak(player, SubSkillType.SWORDS_SWORDS_LIMIT_BREAK)) {
  68. finalDamage += getLimitBreakDamage(player, SubSkillType.SWORDS_SWORDS_LIMIT_BREAK);
  69. }
  70. applyScaledModifiers(initialDamage, finalDamage, event);
  71. startGainXp(mcMMOPlayer, target, PrimarySkillType.SWORDS);
  72. }
  73. private static void processAxeCombat(LivingEntity target, Player player, EntityDamageByEntityEvent event) {
  74. if (event.getCause() == DamageCause.THORNS) {
  75. return;
  76. }
  77. double initialDamage = event.getDamage();
  78. double finalDamage = initialDamage;
  79. Map<DamageModifier, Double> modifiers = getModifiers(event);
  80. McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
  81. AxesManager axesManager = mcMMOPlayer.getAxesManager();
  82. if (axesManager.canActivateAbility()) {
  83. mcMMOPlayer.checkAbilityActivation(PrimarySkillType.AXES);
  84. }
  85. if (axesManager.canUseAxeMastery()) {
  86. finalDamage += axesManager.axeMastery();
  87. }
  88. if (axesManager.canImpact(target)) {
  89. axesManager.impactCheck(target);
  90. } else if (axesManager.canGreaterImpact(target)) {
  91. finalDamage += axesManager.greaterImpact(target);
  92. }
  93. if (axesManager.canUseSkullSplitter(target)) {
  94. axesManager.skullSplitterCheck(target, initialDamage, modifiers);
  95. }
  96. if (axesManager.canCriticalHit(target)) {
  97. finalDamage += axesManager.criticalHit(target, finalDamage);
  98. }
  99. if (canUseLimitBreak(player, SubSkillType.AXES_AXES_LIMIT_BREAK)) {
  100. finalDamage += getLimitBreakDamage(player, SubSkillType.AXES_AXES_LIMIT_BREAK);
  101. }
  102. applyScaledModifiers(initialDamage, finalDamage, event);
  103. startGainXp(mcMMOPlayer, target, PrimarySkillType.AXES);
  104. }
  105. private static void processUnarmedCombat(LivingEntity target, Player player, EntityDamageByEntityEvent event) {
  106. if (event.getCause() == DamageCause.THORNS) {
  107. return;
  108. }
  109. double initialDamage = event.getDamage();
  110. double finalDamage = initialDamage;
  111. McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
  112. UnarmedManager unarmedManager = mcMMOPlayer.getUnarmedManager();
  113. if (unarmedManager.canActivateAbility()) {
  114. mcMMOPlayer.checkAbilityActivation(PrimarySkillType.UNARMED);
  115. }
  116. if (unarmedManager.isPunchingCooldownOver()) {
  117. //Only execute bonuses if the player is not spamming
  118. if (unarmedManager.canUseIronArm()) {
  119. finalDamage += unarmedManager.ironArm();
  120. }
  121. if (unarmedManager.canUseBerserk()) {
  122. finalDamage += unarmedManager.berserkDamage(finalDamage);
  123. }
  124. if (unarmedManager.canDisarm(target)) {
  125. unarmedManager.disarmCheck((Player) target);
  126. }
  127. if (canUseLimitBreak(player, SubSkillType.UNARMED_UNARMED_LIMIT_BREAK)) {
  128. finalDamage += getLimitBreakDamage(player, SubSkillType.UNARMED_UNARMED_LIMIT_BREAK);
  129. }
  130. }
  131. applyScaledModifiers(initialDamage, finalDamage, event);
  132. startGainXp(mcMMOPlayer, target, PrimarySkillType.UNARMED);
  133. Unarmed.lastAttacked = System.currentTimeMillis(); //Track how often the player is punching
  134. }
  135. private static void processTamingCombat(LivingEntity target, Player master, Wolf wolf, EntityDamageByEntityEvent event) {
  136. double initialDamage = event.getDamage();
  137. double finalDamage = initialDamage;
  138. McMMOPlayer mcMMOPlayer = UserManager.getPlayer(master);
  139. TamingManager tamingManager = mcMMOPlayer.getTamingManager();
  140. if (tamingManager.canUseFastFoodService()) {
  141. tamingManager.fastFoodService(wolf, event.getDamage());
  142. }
  143. tamingManager.pummel(target, wolf);
  144. if (tamingManager.canUseSharpenedClaws()) {
  145. finalDamage += tamingManager.getSharpenedClawsDamage();
  146. }
  147. if (tamingManager.canUseGore()) {
  148. finalDamage += tamingManager.gore(target, initialDamage);
  149. }
  150. applyScaledModifiers(initialDamage, finalDamage, event);
  151. startGainXp(mcMMOPlayer, target, PrimarySkillType.TAMING);
  152. }
  153. private static void processArcheryCombat(LivingEntity target, Player player, EntityDamageByEntityEvent event, Arrow arrow) {
  154. double initialDamage = event.getDamage();
  155. McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
  156. ArcheryManager archeryManager = mcMMOPlayer.getArcheryManager();
  157. double finalDamage = event.getDamage();
  158. if (target instanceof Player && PrimarySkillType.UNARMED.getPVPEnabled()) {
  159. UnarmedManager unarmedManager = UserManager.getPlayer((Player) target).getUnarmedManager();
  160. if (unarmedManager.canDeflect()) {
  161. event.setCancelled(unarmedManager.deflectCheck());
  162. if (event.isCancelled()) {
  163. return;
  164. }
  165. }
  166. }
  167. if (archeryManager.canSkillShot()) {
  168. finalDamage += archeryManager.skillShot(initialDamage);
  169. }
  170. if (archeryManager.canDaze(target)) {
  171. finalDamage += archeryManager.daze((Player) target);
  172. }
  173. if (!arrow.hasMetadata(MetadataConstants.INFINITE_ARROW_METAKEY) && archeryManager.canRetrieveArrows()) {
  174. archeryManager.retrieveArrows(target);
  175. }
  176. if (canUseLimitBreak(player, SubSkillType.ARCHERY_ARCHERY_LIMIT_BREAK)) {
  177. finalDamage += getLimitBreakDamage(player, SubSkillType.ARCHERY_ARCHERY_LIMIT_BREAK);
  178. }
  179. double distanceMultiplier = archeryManager.distanceXpBonusMultiplier(target, arrow);
  180. applyScaledModifiers(initialDamage, finalDamage, event);
  181. startGainXp(mcMMOPlayer, target, PrimarySkillType.ARCHERY, arrow.getMetadata(MetadataConstants.BOW_FORCE_METAKEY).get(0).asDouble() * distanceMultiplier);
  182. }
  183. /**
  184. * Apply combat modifiers and process and XP gain.
  185. *
  186. * @param event The event to run the combat checks on.
  187. */
  188. public static void processCombatAttack(EntityDamageByEntityEvent event, Entity attacker, LivingEntity target) {
  189. Entity damager = event.getDamager();
  190. EntityType entityType = damager.getType();
  191. if (target instanceof Player) {
  192. if (Misc.isNPCEntity(target)) {
  193. return;
  194. }
  195. Player player = (Player) target;
  196. if (!UserManager.hasPlayerDataKey(player)) {
  197. return;
  198. }
  199. McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
  200. AcrobaticsManager acrobaticsManager = mcMMOPlayer.getAcrobaticsManager();
  201. if (acrobaticsManager.canDodge(target)) {
  202. event.setDamage(acrobaticsManager.dodgeCheck(event.getDamage()));
  203. }
  204. if (ItemUtils.isSword(player.getInventory().getItemInMainHand())) {
  205. if (!PrimarySkillType.SWORDS.shouldProcess(target)) {
  206. return;
  207. }
  208. SwordsManager swordsManager = mcMMOPlayer.getSwordsManager();
  209. if (swordsManager.canUseCounterAttack(damager)) {
  210. swordsManager.counterAttackChecks((LivingEntity) damager, event.getDamage());
  211. }
  212. }
  213. }
  214. if (attacker instanceof Player && entityType == EntityType.PLAYER) {
  215. Player player = (Player) attacker;
  216. if (!UserManager.hasPlayerDataKey(player)) {
  217. return;
  218. }
  219. ItemStack heldItem = player.getInventory().getItemInMainHand();
  220. if (target instanceof Tameable) {
  221. if (heldItem.getType() == Material.BONE) {
  222. TamingManager tamingManager = UserManager.getPlayer(player).getTamingManager();
  223. if (tamingManager.canUseBeastLore()) {
  224. tamingManager.beastLore(target);
  225. event.setCancelled(true);
  226. return;
  227. }
  228. }
  229. if (isFriendlyPet(player, (Tameable) target)) {
  230. return;
  231. }
  232. }
  233. if (ItemUtils.isSword(heldItem)) {
  234. if (!PrimarySkillType.SWORDS.shouldProcess(target)) {
  235. return;
  236. }
  237. if (PrimarySkillType.SWORDS.getPermissions(player)) {
  238. processSwordCombat(target, player, event);
  239. }
  240. } else if (ItemUtils.isAxe(heldItem)) {
  241. if (!PrimarySkillType.AXES.shouldProcess(target)) {
  242. return;
  243. }
  244. if (PrimarySkillType.AXES.getPermissions(player)) {
  245. processAxeCombat(target, player, event);
  246. }
  247. } else if (ItemUtils.isUnarmed(heldItem)) {
  248. if (!PrimarySkillType.UNARMED.shouldProcess(target)) {
  249. return;
  250. }
  251. if (PrimarySkillType.UNARMED.getPermissions(player)) {
  252. processUnarmedCombat(target, player, event);
  253. }
  254. }
  255. } else if (entityType == EntityType.WOLF) {
  256. Wolf wolf = (Wolf) damager;
  257. AnimalTamer tamer = wolf.getOwner();
  258. if (tamer instanceof Player && PrimarySkillType.TAMING.shouldProcess(target)) {
  259. Player master = (Player) tamer;
  260. if (!Misc.isNPCEntity(master) && PrimarySkillType.TAMING.getPermissions(master)) {
  261. processTamingCombat(target, master, wolf, event);
  262. }
  263. }
  264. } else if (entityType == EntityType.ARROW) {
  265. Arrow arrow = (Arrow) damager;
  266. ProjectileSource projectileSource = arrow.getShooter();
  267. if (projectileSource instanceof Player && PrimarySkillType.ARCHERY.shouldProcess(target)) {
  268. Player player = (Player) projectileSource;
  269. if (!Misc.isNPCEntity(player) && PrimarySkillType.ARCHERY.getPermissions(player)) {
  270. processArcheryCombat(target, player, event, arrow);
  271. }
  272. if (target.getType() != EntityType.CREEPER && !Misc.isNPCEntity(player) && PrimarySkillType.TAMING.getPermissions(player)) {
  273. McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
  274. TamingManager tamingManager = mcMMOPlayer.getTamingManager();
  275. tamingManager.attackTarget(target);
  276. }
  277. }
  278. }
  279. }
  280. /**
  281. * This cleans up names from displaying in chat as hearts
  282. *
  283. * @param entity target entity
  284. */
  285. public static void fixNames(LivingEntity entity) {
  286. List<MetadataValue> metadataValue = entity.getMetadata("mcMMO_oldName");
  287. if (metadataValue.size() <= 0)
  288. return;
  289. if (metadataValue != null) {
  290. OldName oldName = (OldName) metadataValue.get(0);
  291. entity.setCustomName(oldName.asString());
  292. entity.setCustomNameVisible(false);
  293. }
  294. }
  295. public static int getLimitBreakDamage(Player player, SubSkillType subSkillType) {
  296. return RankUtils.getRank(player, subSkillType);
  297. }
  298. /**
  299. * Checks if player has access to their weapons limit break
  300. *
  301. * @param player target player
  302. * @return true if the player has access to the limit break
  303. */
  304. public static boolean canUseLimitBreak(Player player, SubSkillType subSkillType) {
  305. return RankUtils.hasUnlockedSubskill(player, subSkillType)
  306. && Permissions.isSubSkillEnabled(player, subSkillType);
  307. }
  308. /**
  309. * Attempt to damage target for value dmg with reason CUSTOM
  310. *
  311. * @param target LivingEntity which to attempt to damage
  312. * @param damage Amount of damage to attempt to do
  313. */
  314. @Deprecated
  315. public static void dealDamage(LivingEntity target, double damage) {
  316. dealDamage(target, damage, DamageCause.CUSTOM, null);
  317. }
  318. /**
  319. * Attempt to damage target for value dmg with reason ENTITY_ATTACK with damager attacker
  320. *
  321. * @param target LivingEntity which to attempt to damage
  322. * @param damage Amount of damage to attempt to do
  323. * @param attacker Player to pass to event as damager
  324. */
  325. @Deprecated
  326. public static void dealDamage(LivingEntity target, double damage, LivingEntity attacker) {
  327. dealDamage(target, damage, DamageCause.CUSTOM, attacker);
  328. }
  329. /**
  330. * Attempt to damage target for value dmg with reason ENTITY_ATTACK with damager attacker
  331. *
  332. * @param target LivingEntity which to attempt to damage
  333. * @param damage Amount of damage to attempt to do
  334. * @param attacker Player to pass to event as damager
  335. */
  336. public static void dealDamage(LivingEntity target, double damage, Map<DamageModifier, Double> modifiers, LivingEntity attacker) {
  337. if (target.isDead()) {
  338. return;
  339. }
  340. // Aren't we applying the damage twice????
  341. target.damage(getFakeDamageFinalResult(attacker, target, damage, modifiers));
  342. }
  343. /**
  344. * Attempt to damage target for value dmg with reason ENTITY_ATTACK with damager attacker
  345. *
  346. * @param target LivingEntity which to attempt to damage
  347. * @param damage Amount of damage to attempt to do
  348. * @param attacker Player to pass to event as damager
  349. */
  350. @Deprecated
  351. public static void dealDamage(LivingEntity target, double damage, DamageCause cause, Entity attacker) {
  352. if (target.isDead()) {
  353. return;
  354. }
  355. if (canDamage(attacker, target, cause, damage))
  356. target.damage(damage);
  357. }
  358. public static void dealNoInvulnerabilityTickDamage(LivingEntity target, double damage, Entity attacker) {
  359. if (target.isDead()) {
  360. return;
  361. }
  362. double incDmg = getFakeDamageFinalResult(attacker, target, DamageCause.ENTITY_ATTACK, damage);
  363. double newHealth = Math.max(0, target.getHealth() - incDmg);
  364. if (newHealth == 0) {
  365. target.damage(9999, attacker);
  366. } else
  367. target.setHealth(newHealth);
  368. }
  369. public static void dealNoInvulnerabilityTickDamageRupture(LivingEntity target, double damage, Entity attacker, int toolTier) {
  370. if (target.isDead()) {
  371. return;
  372. }
  373. target.setMetadata(MetadataConstants.CUSTOM_DAMAGE_METAKEY, MetadataConstants.metadataValue);
  374. target.damage(damage, attacker);
  375. // //IFrame storage
  376. //// int noDamageTicks = target.getNoDamageTicks();
  377. //
  378. //// String debug = "BLEED DMG RESULT: INC DMG:"+damage+", HP-Before:"+target.getHealth()+", HP-After:";
  379. //
  380. //// double incDmg = getFakeDamageFinalResult(attacker, target, DamageCause.ENTITY_ATTACK, damage);
  381. //
  382. //// double newHealth = Math.max(0, target.getHealth() - incDmg);
  383. //
  384. // //Don't kill things with a stone or wooden weapon
  385. //// if(toolTier < 3 && newHealth == 0)
  386. //// return;
  387. //
  388. // target.setMetadata(mcMMO.CUSTOM_DAMAGE_METAKEY, mcMMO.metadataValue);
  389. //
  390. // if(newHealth == 0 && !(target instanceof Player))
  391. // {
  392. // target.damage(99999, attacker);
  393. // }
  394. // else
  395. // {
  396. //// Vector beforeRuptureVec = new Vector(target.getVelocity().getX(), target.getVelocity().getY(), target.getVelocity().getZ()); ;
  397. // target.damage(damage, attacker);
  398. //// debug+=target.getHealth();
  399. // Bukkit.broadcastMessage(debug);
  400. //// target.setNoDamageTicks(noDamageTicks); //Do not add additional IFrames
  401. //// target.setVelocity(beforeRuptureVec);
  402. // }
  403. }
  404. /**
  405. * Apply Area-of-Effect ability actions.
  406. *
  407. * @param attacker The attacking player
  408. * @param target The defending entity
  409. * @param damage The initial damage amount
  410. * @param type The type of skill being used
  411. */
  412. public static void applyAbilityAoE(Player attacker, LivingEntity target, double damage, Map<DamageModifier, Double> modifiers, PrimarySkillType type) {
  413. int numberOfTargets = getTier(attacker.getInventory().getItemInMainHand()); // The higher the weapon tier, the more targets you hit
  414. double damageAmount = Math.max(damage, 1);
  415. for (Entity entity : target.getNearbyEntities(2.5, 2.5, 2.5)) {
  416. if (numberOfTargets <= 0) {
  417. break;
  418. }
  419. if (Misc.isNPCEntity(entity) || !(entity instanceof LivingEntity) || !shouldBeAffected(attacker, entity)) {
  420. continue;
  421. }
  422. LivingEntity livingEntity = (LivingEntity) entity;
  423. EventUtils.callFakeArmSwingEvent(attacker);
  424. switch (type) {
  425. case SWORDS:
  426. if (entity instanceof Player) {
  427. NotificationManager.sendPlayerInformation((Player) entity, NotificationType.SUBSKILL_MESSAGE, "Swords.Combat.SS.Struck");
  428. }
  429. UserManager.getPlayer(attacker).getSwordsManager().ruptureCheck(target);
  430. break;
  431. case AXES:
  432. if (entity instanceof Player) {
  433. NotificationManager.sendPlayerInformation((Player) entity, NotificationType.SUBSKILL_MESSAGE, "Axes.Combat.SS.Struck");
  434. }
  435. break;
  436. default:
  437. break;
  438. }
  439. dealDamage(livingEntity, damageAmount, attacker);
  440. numberOfTargets--;
  441. }
  442. }
  443. public static void startGainXp(McMMOPlayer mcMMOPlayer, LivingEntity target, PrimarySkillType primarySkillType) {
  444. startGainXp(mcMMOPlayer, target, primarySkillType, 1.0);
  445. }
  446. /**
  447. * Start the task that gives combat XP.
  448. *
  449. * @param mcMMOPlayer The attacking player
  450. * @param target The defending entity
  451. * @param primarySkillType The skill being used
  452. */
  453. private static void startGainXp(McMMOPlayer mcMMOPlayer, LivingEntity target, PrimarySkillType primarySkillType, double multiplier) {
  454. double baseXPMultiplier = 0;
  455. XPGainReason xpGainReason;
  456. if (target instanceof Player) {
  457. if (!mcMMO.getConfigManager().getConfigExperience().isPvpXPEnabled() || PartyManager.inSameParty(mcMMOPlayer.getPlayer(), (Player) target)) {
  458. return;
  459. }
  460. xpGainReason = XPGainReason.PVP;
  461. Player defender = (Player) target;
  462. if (defender.isOnline() && SkillUtils.cooldownExpired(mcMMOPlayer.getRespawnATS(), Misc.PLAYER_RESPAWN_COOLDOWN_SECONDS)) {
  463. baseXPMultiplier = 20 * mcMMO.getDynamicSettingsManager().getExperienceManager().getSpecialCombatXP(SpecialXPKey.PVP);
  464. }
  465. } else {
  466. /*if (mcMMO.getModManager().isCustomEntity(target)) {
  467. baseXP = mcMMO.getModManager().getEntity(target).getXpMultiplier();
  468. }*/
  469. //else if (target instanceof Animals) {
  470. if (target instanceof Animals) {
  471. baseXPMultiplier = mcMMO.getDynamicSettingsManager().getExperienceManager().getSpecialCombatXP(SpecialXPKey.ANIMALS);
  472. } else if (target instanceof Monster) {
  473. EntityType type = target.getType();
  474. baseXPMultiplier = mcMMO.getDynamicSettingsManager().getExperienceManager().getCombatXPMultiplier(type);
  475. } else {
  476. EntityType type = target.getType();
  477. if (mcMMO.getDynamicSettingsManager().getExperienceManager().hasCombatXP(type)) {
  478. //Exploit stuff
  479. if (type == EntityType.IRON_GOLEM) {
  480. if (!((IronGolem) target).isPlayerCreated()) {
  481. baseXPMultiplier = mcMMO.getDynamicSettingsManager().getExperienceManager().getCombatXPMultiplier(type);
  482. }
  483. } else {
  484. baseXPMultiplier = mcMMO.getDynamicSettingsManager().getExperienceManager().getCombatXPMultiplier(type);
  485. }
  486. } else {
  487. baseXPMultiplier = 1.0f;
  488. }
  489. }
  490. if (target.hasMetadata(MetadataConstants.UNNATURAL_MOB_METAKEY)) {
  491. baseXPMultiplier *= mcMMO.getDynamicSettingsManager().getExperienceManager().getSpecialCombatXP(SpecialXPKey.SPAWNED);
  492. }
  493. if (target.hasMetadata(MetadataConstants.PETS_ANIMAL_TRACKING_METAKEY)) {
  494. baseXPMultiplier *= mcMMO.getDynamicSettingsManager().getExperienceManager().getSpecialCombatXP(SpecialXPKey.PETS);
  495. }
  496. xpGainReason = XPGainReason.PVE;
  497. baseXPMultiplier *= 10;
  498. }
  499. baseXPMultiplier *= multiplier;
  500. if (baseXPMultiplier != 0) {
  501. new AwardCombatXpTask(mcMMOPlayer, primarySkillType, baseXPMultiplier, target, xpGainReason).runTaskLater(mcMMO.p, 0);
  502. }
  503. }
  504. /**
  505. * Check to see if the given LivingEntity should be affected by a combat ability.
  506. *
  507. * @param player The attacking Player
  508. * @param entity The defending Entity
  509. * @return true if the Entity should be damaged, false otherwise.
  510. */
  511. private static boolean shouldBeAffected(Player player, Entity entity) {
  512. if (entity instanceof Player) {
  513. Player defender = (Player) entity;
  514. //TODO: NPC Interaction?
  515. if (UserManager.getPlayer(defender) == null)
  516. return true;
  517. if (!defender.getWorld().getPVP() || defender == player || UserManager.getPlayer(defender).getGodMode()) {
  518. return false;
  519. }
  520. if ((PartyManager.inSameParty(player, defender) || PartyManager.areAllies(player, defender)) && !(Permissions.friendlyFire(player) && Permissions.friendlyFire(defender))) {
  521. return false;
  522. }
  523. // Vanished players should not be able to get hit by AoE effects
  524. if (!player.canSee(defender)) {
  525. return false;
  526. }
  527. // Spectators should not be affected
  528. if (defender.getGameMode() == GameMode.SPECTATOR) {
  529. return false;
  530. }
  531. // It may seem a bit redundant but we need a check here to prevent bleed from being applied in applyAbilityAoE()
  532. if (getFakeDamageFinalResult(player, entity, 1.0) == 0) {
  533. return false;
  534. }
  535. } else if (entity instanceof Tameable) {
  536. if (isFriendlyPet(player, (Tameable) entity)) {
  537. // isFriendlyPet ensures that the Tameable is: Tamed, owned by a player, and the owner is in the same party
  538. // So we can make some assumptions here, about our casting and our check
  539. Player owner = (Player) ((Tameable) entity).getOwner();
  540. if (!(Permissions.friendlyFire(player) && Permissions.friendlyFire(owner))) {
  541. return false;
  542. }
  543. }
  544. }
  545. return true;
  546. }
  547. /**
  548. * Checks to see if an entity is currently invincible.
  549. *
  550. * @param entity The {@link LivingEntity} to check
  551. * @param eventDamage The damage from the event the entity is involved in
  552. * @return true if the entity is invincible, false otherwise
  553. */
  554. public static boolean isInvincible(LivingEntity entity, double eventDamage) {
  555. /*
  556. * So apparently if you do more damage to a LivingEntity than its last damage int you bypass the invincibility.
  557. * So yeah, this is for that.
  558. */
  559. return (entity.getNoDamageTicks() > entity.getMaximumNoDamageTicks() / 2.0F) && (eventDamage <= entity.getLastDamage());
  560. }
  561. /**
  562. * Checks to see if an entity is currently friendly toward a given player.
  563. *
  564. * @param attacker The player to check.
  565. * @param pet The entity to check.
  566. * @return true if the entity is friendly, false otherwise
  567. */
  568. public static boolean isFriendlyPet(Player attacker, Tameable pet) {
  569. if (pet.isTamed()) {
  570. AnimalTamer tamer = pet.getOwner();
  571. if (tamer instanceof Player) {
  572. Player owner = (Player) tamer;
  573. return (owner == attacker || PartyManager.inSameParty(attacker, owner) || PartyManager.areAllies(attacker, owner));
  574. }
  575. }
  576. return false;
  577. }
  578. @Deprecated
  579. public static double getFakeDamageFinalResult(Entity attacker, Entity target, double damage) {
  580. return getFakeDamageFinalResult(attacker, target, DamageCause.ENTITY_ATTACK, new EnumMap<>(ImmutableMap.of(DamageModifier.BASE, damage)));
  581. }
  582. @Deprecated
  583. public static double getFakeDamageFinalResult(Entity attacker, Entity target, DamageCause damageCause, double damage) {
  584. EntityDamageEvent damageEvent = sendEntityDamageEvent(attacker, target, damageCause, damage);
  585. if (damageEvent.isCancelled()) {
  586. return 0;
  587. }
  588. return damageEvent.getFinalDamage();
  589. }
  590. public static boolean canDamage(Entity attacker, Entity target, DamageCause damageCause, double damage) {
  591. EntityDamageEvent damageEvent = sendEntityDamageEvent(attacker, target, damageCause, damage);
  592. if (damageEvent.isCancelled()) {
  593. return false;
  594. }
  595. return true;
  596. }
  597. public static EntityDamageEvent sendEntityDamageEvent(Entity attacker, Entity target, DamageCause damageCause, double damage) {
  598. EntityDamageEvent damageEvent = attacker == null ? new FakeEntityDamageEvent(target, damageCause, damage) : new FakeEntityDamageByEntityEvent(attacker, target, damageCause, damage);
  599. mcMMO.p.getServer().getPluginManager().callEvent(damageEvent);
  600. return damageEvent;
  601. }
  602. public static double getFakeDamageFinalResult(Entity attacker, Entity target, Map<DamageModifier, Double> modifiers) {
  603. return getFakeDamageFinalResult(attacker, target, DamageCause.ENTITY_ATTACK, modifiers);
  604. }
  605. public static double getFakeDamageFinalResult(Entity attacker, Entity target, double damage, Map<DamageModifier, Double> modifiers) {
  606. return getFakeDamageFinalResult(attacker, target, DamageCause.ENTITY_ATTACK, getScaledModifiers(damage, modifiers));
  607. }
  608. public static double getFakeDamageFinalResult(Entity attacker, Entity target, DamageCause cause, Map<DamageModifier, Double> modifiers) {
  609. EntityDamageEvent damageEvent = attacker == null ? new FakeEntityDamageEvent(target, cause, modifiers) : new FakeEntityDamageByEntityEvent(attacker, target, cause, modifiers);
  610. mcMMO.p.getServer().getPluginManager().callEvent(damageEvent);
  611. if (damageEvent.isCancelled()) {
  612. return 0;
  613. }
  614. return damageEvent.getFinalDamage();
  615. }
  616. private static Map<DamageModifier, Double> getModifiers(EntityDamageEvent event) {
  617. Map<DamageModifier, Double> modifiers = new HashMap<>();
  618. for (DamageModifier modifier : DamageModifier.values()) {
  619. modifiers.put(modifier, event.getDamage(modifier));
  620. }
  621. return modifiers;
  622. }
  623. private static Map<DamageModifier, Double> getScaledModifiers(double damage, Map<DamageModifier, Double> modifiers) {
  624. Map<DamageModifier, Double> scaledModifiers = new HashMap<>();
  625. for (DamageModifier modifier : modifiers.keySet()) {
  626. if (modifier == DamageModifier.BASE) {
  627. scaledModifiers.put(modifier, damage);
  628. continue;
  629. }
  630. scaledModifiers.put(modifier, damage * modifiers.get(modifier));
  631. }
  632. return scaledModifiers;
  633. }
  634. public static void applyScaledModifiers(double initialDamage, double finalDamage, EntityDamageByEntityEvent event) {
  635. // No additional damage
  636. if (initialDamage == finalDamage) {
  637. return;
  638. }
  639. for (DamageModifier modifier : DamageModifier.values()) {
  640. if (!event.isApplicable(modifier)) {
  641. continue;
  642. }
  643. if (modifier == DamageModifier.BASE) {
  644. event.setDamage(modifier, finalDamage);
  645. continue;
  646. }
  647. event.setDamage(modifier, finalDamage / initialDamage * event.getDamage(modifier));
  648. }
  649. }
  650. /**
  651. * Get the upgrade tier of the item in hand.
  652. *
  653. * @param inHand The item to check the tier of
  654. * @return the tier of the item
  655. */
  656. private static int getTier(ItemStack inHand) {
  657. int tier = 0;
  658. if (ItemUtils.isWoodTool(inHand)) {
  659. tier = 1;
  660. } else if (ItemUtils.isStoneTool(inHand)) {
  661. tier = 2;
  662. } else if (ItemUtils.isIronTool(inHand)) {
  663. tier = 3;
  664. } else if (ItemUtils.isGoldTool(inHand)) {
  665. tier = 1;
  666. } else if (ItemUtils.isDiamondTool(inHand)) {
  667. tier = 4;
  668. }
  669. /*else if (mcMMO.getModManager().isCustomTool(inHand)) {
  670. tier = mcMMO.getModManager().getTool(inHand).getTier();
  671. }*/
  672. return tier;
  673. }
  674. public static void handleHealthbars(Entity attacker, LivingEntity target, double damage, mcMMO plugin) {
  675. if (!(attacker instanceof Player)) {
  676. return;
  677. }
  678. Player player = (Player) attacker;
  679. if (Misc.isNPCEntity(player) || Misc.isNPCEntity(target)) {
  680. return;
  681. }
  682. if (!player.hasMetadata(MetadataConstants.PLAYER_DATA_METAKEY)) {
  683. return;
  684. }
  685. MobHealthbarUtils.handleMobHealthbars(target, damage, plugin);
  686. }
  687. }