Combat.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. package com.gmail.nossr50;
  2. import org.bukkit.Bukkit;
  3. import org.bukkit.Material;
  4. import org.bukkit.entity.AnimalTamer;
  5. import org.bukkit.entity.Animals;
  6. import org.bukkit.entity.Arrow;
  7. import org.bukkit.entity.Entity;
  8. import org.bukkit.entity.EntityType;
  9. import org.bukkit.entity.LivingEntity;
  10. import org.bukkit.entity.Player;
  11. import org.bukkit.entity.Wolf;
  12. import org.bukkit.event.entity.EntityDamageByEntityEvent;
  13. import org.bukkit.event.entity.EntityDamageEvent;
  14. import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
  15. import org.bukkit.inventory.ItemStack;
  16. import com.gmail.nossr50.config.LoadProperties;
  17. import com.gmail.nossr50.datatypes.PlayerProfile;
  18. import com.gmail.nossr50.datatypes.SkillType;
  19. import com.gmail.nossr50.events.FakeEntityDamageByEntityEvent;
  20. import com.gmail.nossr50.events.FakeEntityDamageEvent;
  21. import com.gmail.nossr50.locale.mcLocale;
  22. import com.gmail.nossr50.party.Party;
  23. import com.gmail.nossr50.runnables.GainXp;
  24. import com.gmail.nossr50.skills.Acrobatics;
  25. import com.gmail.nossr50.skills.Archery;
  26. import com.gmail.nossr50.skills.Axes;
  27. import com.gmail.nossr50.skills.Skills;
  28. import com.gmail.nossr50.skills.Swords;
  29. import com.gmail.nossr50.skills.Taming;
  30. import com.gmail.nossr50.skills.Unarmed;
  31. public class Combat {
  32. /**
  33. * Apply combat modifiers and process and XP gain.
  34. *
  35. * @param event The event to run the combat checks on.
  36. * @param plugin mcMMO plugin instance
  37. */
  38. public static void combatChecks(EntityDamageByEntityEvent event, mcMMO plugin) {
  39. if (event.getDamage() == 0 || event.getEntity().isDead()) {
  40. return;
  41. }
  42. Entity damager = event.getDamager();
  43. LivingEntity target = (LivingEntity) event.getEntity();
  44. int damage = event.getDamage();
  45. EntityType damagerType = damager.getType();
  46. EntityType targetType = target.getType();
  47. switch (damagerType) {
  48. case PLAYER:
  49. Player attacker = (Player) event.getDamager();
  50. ItemStack itemInHand = attacker.getItemInHand();
  51. PlayerProfile PPa = Users.getProfile(attacker);
  52. combatAbilityChecks(attacker);
  53. if (ItemChecks.isSword(itemInHand) && mcPermissions.getInstance().swords(attacker)) {
  54. if (!plugin.misc.bleedTracker.contains(target)) {
  55. Swords.bleedCheck(attacker, target, plugin);
  56. }
  57. if (PPa.getSerratedStrikesMode()) {
  58. applyAbilityAoE(attacker, target, damage, plugin, SkillType.SWORDS);
  59. }
  60. startGainXp(attacker, PPa, target, SkillType.SWORDS, plugin);
  61. }
  62. else if (ItemChecks.isAxe(itemInHand) && mcPermissions.getInstance().axes(attacker)) {
  63. Axes.axesBonus(attacker, event);
  64. Axes.axeCriticalCheck(attacker, event);
  65. Axes.impact(attacker, target, event);
  66. if (PPa.getSkullSplitterMode()) {
  67. applyAbilityAoE(attacker, target, damage, plugin, SkillType.AXES);
  68. }
  69. startGainXp(attacker, PPa, target, SkillType.AXES, plugin);
  70. }
  71. else if (itemInHand.getType().equals(Material.AIR) && mcPermissions.getInstance().unarmed(attacker)) {
  72. Unarmed.unarmedBonus(attacker, event);
  73. if (PPa.getBerserkMode()) {
  74. event.setDamage(damage + (damage / 2));
  75. }
  76. if (targetType.equals(EntityType.PLAYER)) {
  77. Unarmed.disarmProcCheck(attacker, (Player) target);
  78. }
  79. startGainXp(attacker, PPa, target, SkillType.UNARMED, plugin);
  80. }
  81. else if (itemInHand.getType().equals(Material.BONE) && mcPermissions.getInstance().taming(attacker) && targetType.equals(EntityType.WOLF)) {
  82. Wolf wolf = (Wolf) target;
  83. String message = mcLocale.getString("Combat.BeastLore") + " ";
  84. int health = wolf.getHealth();
  85. event.setCancelled(true);
  86. if (wolf.isTamed()) {
  87. message = message.concat(mcLocale.getString("Combat.BeastLoreOwner", new Object[] {Taming.getOwnerName(wolf)}) + " ");
  88. message = message.concat(mcLocale.getString("Combat.BeastLoreHealthWolfTamed", new Object[] {health}));
  89. }
  90. else {
  91. message = message.concat(mcLocale.getString("Combat.BeastLoreHealthWolf", new Object[] {health}));
  92. }
  93. attacker.sendMessage(message);
  94. }
  95. break;
  96. case WOLF:
  97. Wolf wolf = (Wolf) damager;
  98. if (wolf.isTamed() && wolf.getOwner() instanceof Player) {
  99. Player master = (Player) wolf.getOwner();
  100. PlayerProfile PPo = Users.getProfile(master);
  101. if (mcPermissions.getInstance().taming(master)) {
  102. Taming.fastFoodService(PPo, wolf, event);
  103. Taming.sharpenedClaws(PPo, event);
  104. Taming.gore(PPo, event, master, plugin);
  105. startGainXp(master, PPo, target, SkillType.TAMING, plugin);
  106. }
  107. }
  108. break;
  109. case ARROW:
  110. archeryCheck((EntityDamageByEntityEvent) event, plugin);
  111. break;
  112. default:
  113. break;
  114. }
  115. if (targetType.equals(EntityType.PLAYER)) {
  116. Swords.counterAttackChecks(event);
  117. Acrobatics.dodgeChecks(event);
  118. }
  119. }
  120. /**
  121. * Process combat abilities based on weapon preparation modes.
  122. *
  123. * @param attacker The player attacking
  124. */
  125. public static void combatAbilityChecks(Player attacker) {
  126. PlayerProfile PPa = Users.getProfile(attacker);
  127. if (PPa.getAxePreparationMode()) {
  128. Skills.abilityCheck(attacker, SkillType.AXES);
  129. }
  130. else if (PPa.getSwordsPreparationMode()) {
  131. Skills.abilityCheck(attacker, SkillType.SWORDS);
  132. }
  133. else if (PPa.getFistsPreparationMode()) {
  134. Skills.abilityCheck(attacker, SkillType.UNARMED);
  135. }
  136. }
  137. /**
  138. * Process archery abilities.
  139. *
  140. * @param event The event to run the archery checks on.
  141. * @param pluginx mcMMO plugin instance
  142. */
  143. public static void archeryCheck(EntityDamageByEntityEvent event, mcMMO pluginx) {
  144. Arrow arrow = (Arrow) event.getDamager();
  145. LivingEntity shooter = arrow.getShooter();
  146. LivingEntity target = (LivingEntity) event.getEntity();
  147. if (target instanceof Player) {
  148. Player defender = (Player) target;
  149. PlayerProfile PPd = Users.getProfile(defender);
  150. boolean deflect = false;
  151. if (mcPermissions.getInstance().unarmed(defender) && defender.getItemInHand().getType().equals(Material.AIR)) {
  152. if (PPd.getSkillLevel(SkillType.UNARMED) >= 1000 && (Math.random() * 1000 <= 500)) {
  153. deflect = true;
  154. }
  155. else if (Math.random() * 1000 <= (PPd.getSkillLevel(SkillType.UNARMED) / 2)) {
  156. deflect = true;
  157. }
  158. if (deflect) {
  159. event.setCancelled(true);
  160. defender.sendMessage(mcLocale.getString("Combat.ArrowDeflect"));
  161. return;
  162. }
  163. }
  164. }
  165. if (shooter instanceof Player) {
  166. Player attacker = (Player) shooter;
  167. PlayerProfile PPa = Users.getProfile(attacker);
  168. int damage = event.getDamage();
  169. if (mcPermissions.getInstance().archery(attacker) && damage > 0) {
  170. Archery.trackArrows(pluginx, target, PPa);
  171. Archery.ignitionCheck(target, attacker);
  172. startGainXp(attacker, PPa, target, SkillType.ARCHERY, pluginx);
  173. if (target instanceof Player) {
  174. Player defender = (Player) target;
  175. PlayerProfile PPd = Users.getProfile(defender);
  176. if (PPa.inParty() && PPd.inParty() && Party.getInstance().inSameParty(defender, attacker)) {
  177. event.setCancelled(true);
  178. return;
  179. }
  180. Archery.dazeCheck(defender, attacker);
  181. }
  182. }
  183. }
  184. }
  185. /**
  186. * Attempt to damage target for value dmg with reason CUSTOM
  187. *
  188. * @param target LivingEntity which to attempt to damage
  189. * @param dmg Amount of damage to attempt to do
  190. */
  191. public static void dealDamage(LivingEntity target, int dmg) {
  192. dealDamage(target, dmg, EntityDamageEvent.DamageCause.CUSTOM);
  193. }
  194. /**
  195. * Attempt to damage target for value dmg with reason cause
  196. *
  197. * @param target LivingEntity which to attempt to damage
  198. * @param dmg Amount of damage to attempt to do
  199. * @param cause DamageCause to pass to damage event
  200. */
  201. private static void dealDamage(LivingEntity target, int dmg, DamageCause cause) {
  202. if (LoadProperties.eventCallback) {
  203. EntityDamageEvent ede = (EntityDamageEvent) new FakeEntityDamageEvent(target, cause, dmg);
  204. Bukkit.getPluginManager().callEvent(ede);
  205. if (ede.isCancelled()) {
  206. return;
  207. }
  208. target.damage(ede.getDamage());
  209. }
  210. else {
  211. target.damage(dmg);
  212. }
  213. }
  214. /**
  215. * Attempt to damage target for value dmg with reason ENTITY_ATTACK with damager attacker
  216. *
  217. * @param target LivingEntity which to attempt to damage
  218. * @param dmg Amount of damage to attempt to do
  219. * @param attacker Player to pass to event as damager
  220. */
  221. private static void dealDamage(LivingEntity target, int dmg, Player attacker) {
  222. if (LoadProperties.eventCallback) {
  223. EntityDamageEvent ede = (EntityDamageByEntityEvent) new FakeEntityDamageByEntityEvent(attacker, target, EntityDamageEvent.DamageCause.ENTITY_ATTACK, dmg);
  224. Bukkit.getPluginManager().callEvent(ede);
  225. if (ede.isCancelled()) {
  226. return;
  227. }
  228. target.damage(ede.getDamage());
  229. }
  230. else {
  231. target.damage(dmg);
  232. }
  233. }
  234. /**
  235. * Apply Area-of-Effect ability actions.
  236. *
  237. * @param attacker The attacking player
  238. * @param target The defending entity
  239. * @param damage The initial damage amount
  240. * @param plugin mcMMO plugin instance
  241. * @param type The type of skill being used
  242. */
  243. private static void applyAbilityAoE(Player attacker, LivingEntity target, int damage, mcMMO plugin, SkillType type) {
  244. int numberOfTargets = m.getTier(attacker.getItemInHand()); //The higher the weapon tier, the more targets you hit
  245. int damageAmount = 0;
  246. if (type.equals(SkillType.AXES)) {
  247. damageAmount = damage / 2;
  248. }
  249. else if (type.equals(SkillType.SWORDS)) {
  250. damageAmount = damage / 4;
  251. }
  252. if (damageAmount < 1) {
  253. damageAmount = 1;
  254. }
  255. for (Entity entity : target.getNearbyEntities(2.5, 2.5, 2.5)) {
  256. EntityType entityType = entity.getType();
  257. if (entityType.equals(EntityType.WOLF)) {
  258. Wolf wolf = (Wolf) entity;
  259. AnimalTamer tamer = wolf.getOwner();
  260. if (tamer instanceof Player) {
  261. Player owner = (Player) tamer;
  262. if (owner.equals(attacker) || Party.getInstance().inSameParty(attacker, owner)) {
  263. continue;
  264. }
  265. }
  266. }
  267. if (entity instanceof LivingEntity && numberOfTargets >= 1) {
  268. if (entityType.equals(EntityType.PLAYER)) {
  269. Player defender = (Player) entity;
  270. PlayerProfile PP = Users.getProfile(defender);
  271. //Reasons why the target shouldn't be hit
  272. if (PP.getGodMode()) {
  273. continue;
  274. }
  275. if (defender.getName().equals(attacker.getName())) { //Is this even possible?
  276. continue;
  277. }
  278. if (Party.getInstance().inSameParty(attacker, defender)) {
  279. continue;
  280. }
  281. if (defender.isDead()) {
  282. continue;
  283. }
  284. //Apply effect to players only if PVP is enabled
  285. if (target.getWorld().getPVP()) {
  286. String message = "";
  287. if (type.equals(SkillType.AXES)) {
  288. message = mcLocale.getString("Axes.HitByCleave");
  289. }
  290. else if (type.equals(SkillType.SWORDS)) {
  291. message = mcLocale.getString("Swords.HitBySerratedStrikes");
  292. }
  293. dealDamage(defender, damageAmount, attacker);
  294. defender.sendMessage(message);
  295. if (type.equals(SkillType.SWORDS)) {
  296. PP.addBleedTicks(5);
  297. }
  298. numberOfTargets--;
  299. }
  300. }
  301. else {
  302. LivingEntity livingEntity = (LivingEntity) entity;
  303. if (type.equals(SkillType.SWORDS) && !plugin.misc.bleedTracker.contains(entity)) {
  304. plugin.misc.addToBleedQue(livingEntity);
  305. }
  306. dealDamage(livingEntity, damageAmount, attacker);
  307. numberOfTargets--;
  308. }
  309. }
  310. }
  311. }
  312. /**
  313. * Start the task that gives combat XP.
  314. *
  315. * @param attacker The attacking player
  316. * @param PP The player's PlayerProfile
  317. * @param target The defending entity
  318. * @param skillType The skill being used
  319. * @param plugin mcMMO plugin instance
  320. */
  321. public static void startGainXp(Player attacker, PlayerProfile PP, LivingEntity target, SkillType skillType, mcMMO pluginx) {
  322. double baseXP = 0;
  323. if (target instanceof Player) {
  324. if (!LoadProperties.pvpxp) {
  325. return;
  326. }
  327. Player defender = (Player) target;
  328. PlayerProfile PPd = Users.getProfile(defender);
  329. if (System.currentTimeMillis() >= (PPd.getRespawnATS() * 1000) + 5000 && ((PPd.getLastLogin() + 5) * 1000) < System.currentTimeMillis() && defender.getHealth() >= 1) {
  330. baseXP = 20 * LoadProperties.pvpxprewardmodifier;
  331. }
  332. }
  333. else if (!target.hasMetadata("fromMobSpawner")) {
  334. if (target instanceof Animals && !target.hasMetadata("summoned")) {
  335. baseXP = LoadProperties.animalXP;
  336. }
  337. else {
  338. EntityType type = target.getType();
  339. switch (type) {
  340. case BLAZE:
  341. baseXP = LoadProperties.blazeXP;
  342. break;
  343. case CAVE_SPIDER:
  344. baseXP = LoadProperties.cavespiderXP;
  345. break;
  346. case CREEPER:
  347. baseXP = LoadProperties.creeperXP;
  348. break;
  349. case ENDER_DRAGON:
  350. baseXP = LoadProperties.enderdragonXP;
  351. break;
  352. case ENDERMAN:
  353. baseXP = LoadProperties.endermanXP;
  354. break;
  355. case GHAST:
  356. baseXP = LoadProperties.ghastXP;
  357. break;
  358. case MAGMA_CUBE:
  359. baseXP = LoadProperties.magmacubeXP;
  360. break;
  361. case PIG_ZOMBIE:
  362. baseXP = LoadProperties.pigzombieXP;
  363. break;
  364. case SILVERFISH:
  365. baseXP = LoadProperties.silverfishXP;
  366. break;
  367. case SKELETON:
  368. baseXP = LoadProperties.skeletonXP;
  369. break;
  370. case SLIME:
  371. baseXP = LoadProperties.slimeXP;
  372. break;
  373. case SPIDER:
  374. baseXP = LoadProperties.spiderXP;
  375. break;
  376. case ZOMBIE:
  377. baseXP = LoadProperties.zombieXP;
  378. break;
  379. default:
  380. break;
  381. }
  382. }
  383. baseXP *= 10;
  384. }
  385. if (baseXP != 0) {
  386. Bukkit.getScheduler().scheduleSyncDelayedTask(pluginx, new GainXp(attacker, PP, skillType, baseXP, target), 0);
  387. }
  388. }
  389. }