Combat.java 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. package com.gmail.nossr50.util;
  2. import org.bukkit.Material;
  3. import org.bukkit.entity.AnimalTamer;
  4. import org.bukkit.entity.Animals;
  5. import org.bukkit.entity.Arrow;
  6. import org.bukkit.entity.Entity;
  7. import org.bukkit.entity.EntityType;
  8. import org.bukkit.entity.IronGolem;
  9. import org.bukkit.entity.LivingEntity;
  10. import org.bukkit.entity.Player;
  11. import org.bukkit.entity.Tameable;
  12. import org.bukkit.entity.Wolf;
  13. import org.bukkit.event.entity.EntityDamageByEntityEvent;
  14. import org.bukkit.event.entity.EntityDamageEvent;
  15. import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
  16. import org.bukkit.event.player.PlayerAnimationEvent;
  17. import org.bukkit.inventory.ItemStack;
  18. import com.gmail.nossr50.mcMMO;
  19. import com.gmail.nossr50.config.Config;
  20. import com.gmail.nossr50.datatypes.AbilityType;
  21. import com.gmail.nossr50.datatypes.PlayerProfile;
  22. import com.gmail.nossr50.datatypes.SkillType;
  23. import com.gmail.nossr50.datatypes.ToolType;
  24. import com.gmail.nossr50.events.fake.FakeEntityDamageByEntityEvent;
  25. import com.gmail.nossr50.events.fake.FakeEntityDamageEvent;
  26. import com.gmail.nossr50.locale.LocaleLoader;
  27. import com.gmail.nossr50.party.PartyManager;
  28. import com.gmail.nossr50.runnables.BleedTimer;
  29. import com.gmail.nossr50.runnables.GainXp;
  30. import com.gmail.nossr50.skills.acrobatics.AcrobaticsManager;
  31. import com.gmail.nossr50.skills.combat.Archery;
  32. import com.gmail.nossr50.skills.combat.Axes;
  33. import com.gmail.nossr50.skills.combat.Swords;
  34. import com.gmail.nossr50.skills.combat.Taming;
  35. import com.gmail.nossr50.skills.combat.Unarmed;
  36. public class Combat {
  37. private static Config configInstance = Config.getInstance();
  38. private static Permissions permInstance = Permissions.getInstance();
  39. /**
  40. * Apply combat modifiers and process and XP gain.
  41. *
  42. * @param event The event to run the combat checks on.
  43. */
  44. public static void combatChecks(EntityDamageByEntityEvent event) {
  45. if (event.getDamage() == 0 || event.getEntity().isDead()) {
  46. return;
  47. }
  48. Entity damager = event.getDamager();
  49. LivingEntity target = (LivingEntity) event.getEntity();
  50. boolean targetIsPlayer = target instanceof Player;
  51. boolean targetIsTamedPet = (target instanceof Tameable) ? ((Tameable) target).isTamed() : false;
  52. if (damager instanceof Player) {
  53. Player attacker = (Player) event.getDamager();
  54. ItemStack itemInHand = attacker.getItemInHand();
  55. PlayerProfile PPa = Users.getProfile(attacker);
  56. combatAbilityChecks(attacker);
  57. if (ItemChecks.isSword(itemInHand) && permInstance.swords(attacker)) {
  58. if (!configInstance.getSwordsPVP()) {
  59. if (targetIsPlayer || targetIsTamedPet) {
  60. return;
  61. }
  62. }
  63. if (!configInstance.getSwordsPVE()) {
  64. if (!targetIsPlayer || !targetIsTamedPet) {
  65. return;
  66. }
  67. }
  68. if (permInstance.swordsBleed(attacker)) {
  69. Swords.bleedCheck(attacker, target);
  70. }
  71. if (PPa.getAbilityMode(AbilityType.SERRATED_STRIKES) && permInstance.serratedStrikes(attacker)) {
  72. applyAbilityAoE(attacker, target, event.getDamage() / 4, SkillType.SWORDS);
  73. BleedTimer.add(target, 5);
  74. }
  75. startGainXp(attacker, PPa, target, SkillType.SWORDS);
  76. }
  77. else if (ItemChecks.isAxe(itemInHand) && permInstance.axes(attacker)) {
  78. if (!configInstance.getAxesPVP()) {
  79. if (targetIsPlayer || targetIsTamedPet) {
  80. return;
  81. }
  82. }
  83. if (!configInstance.getAxesPVE()) {
  84. if (!targetIsPlayer || !targetIsTamedPet) {
  85. return;
  86. }
  87. }
  88. if (permInstance.axeBonus(attacker)) {
  89. Axes.axesBonus(attacker, event);
  90. }
  91. if (permInstance.criticalHit(attacker)) {
  92. Axes.axeCriticalCheck(attacker, event);
  93. }
  94. if (permInstance.impact(attacker)) {
  95. Axes.impact(attacker, target, event);
  96. }
  97. if (PPa.getAbilityMode(AbilityType.SKULL_SPLIITER) && permInstance.skullSplitter(attacker)) {
  98. applyAbilityAoE(attacker, target, event.getDamage() / 2, SkillType.AXES);
  99. }
  100. startGainXp(attacker, PPa, target, SkillType.AXES);
  101. }
  102. else if (itemInHand.getType().equals(Material.AIR) && permInstance.unarmed(attacker)) {
  103. if (!configInstance.getUnarmedPVP()) {
  104. if (targetIsPlayer || targetIsTamedPet) {
  105. return;
  106. }
  107. }
  108. if (!configInstance.getUnarmedPVE()) {
  109. if (!targetIsPlayer || !targetIsTamedPet) {
  110. return;
  111. }
  112. }
  113. if (permInstance.unarmedBonus(attacker)) {
  114. Unarmed.unarmedBonus(PPa, event);
  115. }
  116. if (PPa.getAbilityMode(AbilityType.BERSERK) && permInstance.berserk(attacker)) {
  117. event.setDamage((int) (event.getDamage() * 1.5));
  118. }
  119. if (targetIsPlayer && permInstance.disarm(attacker)) {
  120. Unarmed.disarmProcCheck(attacker, (Player) target);
  121. }
  122. startGainXp(attacker, PPa, target, SkillType.UNARMED);
  123. }
  124. else if (itemInHand.getType().equals(Material.BONE) && permInstance.beastLore(attacker)) {
  125. Taming.beastLore(event, target, attacker);
  126. }
  127. }
  128. else if (damager instanceof Wolf) {
  129. Wolf wolf = (Wolf) damager;
  130. if (wolf.isTamed() && wolf.getOwner() instanceof Player) {
  131. Player master = (Player) wolf.getOwner();
  132. PlayerProfile PPo = Users.getProfile(master);
  133. if (!configInstance.getTamingPVP()) {
  134. if (targetIsPlayer || targetIsTamedPet) {
  135. return;
  136. }
  137. }
  138. if (!configInstance.getTamingPVE()) {
  139. if (!targetIsPlayer || !targetIsTamedPet) {
  140. return;
  141. }
  142. }
  143. if (permInstance.fastFoodService(master)) {
  144. Taming.fastFoodService(PPo, wolf, event.getDamage());
  145. }
  146. if (permInstance.sharpenedClaws(master)) {
  147. Taming.sharpenedClaws(PPo, event);
  148. }
  149. if (permInstance.gore(master)) {
  150. Taming.gore(PPo, event, master);
  151. }
  152. if (permInstance.taming(master)) {
  153. startGainXp(master, PPo, target, SkillType.TAMING);
  154. }
  155. }
  156. }
  157. else if (damager instanceof Arrow) {
  158. LivingEntity shooter = ((Arrow) damager).getShooter();
  159. if (shooter.getType() != EntityType.PLAYER) {
  160. return;
  161. }
  162. if (targetIsPlayer || targetIsTamedPet) {
  163. if (!configInstance.getArcheryPVP()) {
  164. return;
  165. }
  166. }
  167. else if (!configInstance.getArcheryPVE()) {
  168. return;
  169. }
  170. archeryCheck((Player) shooter, target, event);
  171. }
  172. if (target instanceof Player) {
  173. AcrobaticsManager acroManager = new AcrobaticsManager((Player) target);
  174. if (configInstance.getSwordsPVP() && damager instanceof Player) {
  175. Swords.counterAttackChecks(damager, (Player) target, event.getDamage());
  176. }
  177. if (configInstance.getSwordsPVE() && !(damager instanceof Player)) {
  178. Swords.counterAttackChecks(damager, (Player) target, event.getDamage());
  179. }
  180. if (configInstance.getAcrobaticsPVP() && damager instanceof Player) {
  181. acroManager.dodgeCheck(event);
  182. }
  183. if (configInstance.getAcrobaticsPVE() && !(damager instanceof Player)) {
  184. acroManager.dodgeCheck(event);
  185. }
  186. }
  187. }
  188. /**
  189. * Process combat abilities based on weapon preparation modes.
  190. *
  191. * @param attacker The player attacking
  192. */
  193. public static void combatAbilityChecks(Player attacker) {
  194. PlayerProfile PPa = Users.getProfile(attacker);
  195. if (PPa.getToolPreparationMode(ToolType.AXE)) {
  196. Skills.abilityCheck(attacker, SkillType.AXES);
  197. }
  198. else if (PPa.getToolPreparationMode(ToolType.SWORD)) {
  199. Skills.abilityCheck(attacker, SkillType.SWORDS);
  200. }
  201. else if (PPa.getToolPreparationMode(ToolType.FISTS)) {
  202. Skills.abilityCheck(attacker, SkillType.UNARMED);
  203. }
  204. }
  205. /**
  206. * Process archery abilities.
  207. *
  208. * @param shooter The player shooting
  209. * @param target The defending entity
  210. * @param event The event to run the archery checks on.
  211. */
  212. public static void archeryCheck(Player shooter, LivingEntity target, EntityDamageByEntityEvent event) {
  213. if (target instanceof Player) {
  214. Player defender = (Player) target;
  215. if (defender.getItemInHand().getType().equals(Material.AIR)) {
  216. if (configInstance.getUnarmedPVP()) {
  217. Unarmed.deflectCheck(defender, event);
  218. }
  219. }
  220. }
  221. if (permInstance.archery(shooter)) {
  222. if (permInstance.archeryBonus(shooter)) {
  223. /*Archery needs a damage bonus to be viable in PVP*/
  224. int skillLvl = Users.getProfile(shooter).getSkillLevel(SkillType.ARCHERY);
  225. double dmgBonusPercent = ((skillLvl / 50) * 0.1D);
  226. /* Cap maximum bonus at 200% */
  227. if (dmgBonusPercent > 2) {
  228. dmgBonusPercent = 2;
  229. }
  230. /* Every 50 skill levels Archery gains 10% damage bonus, set that here */
  231. //TODO: Work in progress for balancing out Archery, will work on it more later...
  232. int damage = event.getDamage();
  233. int archeryBonus = (int) (damage * dmgBonusPercent);
  234. event.setDamage(damage + archeryBonus);
  235. }
  236. if (target instanceof Player && permInstance.daze(shooter)) {
  237. Archery.dazeCheck((Player) target, shooter, event);
  238. }
  239. PlayerProfile PP = Users.getProfile(shooter);
  240. if (permInstance.trackArrows(shooter)) {
  241. Archery.trackArrows(target, PP);
  242. }
  243. if (target != shooter) {
  244. startGainXp(shooter, PP, target, SkillType.ARCHERY);
  245. }
  246. }
  247. }
  248. /**
  249. * Attempt to damage target for value dmg with reason CUSTOM
  250. *
  251. * @param target LivingEntity which to attempt to damage
  252. * @param dmg Amount of damage to attempt to do
  253. */
  254. public static void dealDamage(LivingEntity target, int dmg) {
  255. dealDamage(target, dmg, EntityDamageEvent.DamageCause.CUSTOM);
  256. }
  257. /**
  258. * Attempt to damage target for value dmg with reason cause
  259. *
  260. * @param target LivingEntity which to attempt to damage
  261. * @param dmg Amount of damage to attempt to do
  262. * @param cause DamageCause to pass to damage event
  263. */
  264. private static void dealDamage(LivingEntity target, int dmg, DamageCause cause) {
  265. if (configInstance.getEventCallbackEnabled()) {
  266. EntityDamageEvent ede = new FakeEntityDamageEvent(target, cause, dmg);
  267. mcMMO.p.getServer().getPluginManager().callEvent(ede);
  268. if (ede.isCancelled()) {
  269. return;
  270. }
  271. target.damage(ede.getDamage());
  272. }
  273. else {
  274. target.damage(dmg);
  275. }
  276. }
  277. /**
  278. * Attempt to damage target for value dmg with reason ENTITY_ATTACK with damager attacker
  279. *
  280. * @param target LivingEntity which to attempt to damage
  281. * @param dmg Amount of damage to attempt to do
  282. * @param attacker Player to pass to event as damager
  283. */
  284. private static void dealDamage(LivingEntity target, int dmg, Player attacker) {
  285. if (configInstance.getEventCallbackEnabled()) {
  286. EntityDamageEvent ede = new FakeEntityDamageByEntityEvent(attacker, target, EntityDamageEvent.DamageCause.ENTITY_ATTACK, dmg);
  287. mcMMO.p.getServer().getPluginManager().callEvent(ede);
  288. if (ede.isCancelled()) {
  289. return;
  290. }
  291. target.damage(ede.getDamage());
  292. }
  293. else {
  294. target.damage(dmg);
  295. }
  296. }
  297. /**
  298. * Apply Area-of-Effect ability actions.
  299. *
  300. * @param attacker The attacking player
  301. * @param target The defending entity
  302. * @param damage The initial damage amount
  303. * @param type The type of skill being used
  304. */
  305. private static void applyAbilityAoE(Player attacker, LivingEntity target, int damage, SkillType type) {
  306. ItemStack inHand = attacker.getItemInHand();
  307. if (ModChecks.isCustomTool(inHand) && !ModChecks.getToolFromItemStack(inHand).isAbilityEnabled()) {
  308. return;
  309. }
  310. int numberOfTargets = Misc.getTier(attacker.getItemInHand()); //The higher the weapon tier, the more targets you hit
  311. int damageAmount = damage;
  312. if (damageAmount < 1) {
  313. damageAmount = 1;
  314. }
  315. for (Entity entity : target.getNearbyEntities(2.5, 2.5, 2.5)) {
  316. if (!(entity instanceof LivingEntity)) {
  317. continue;
  318. }
  319. if (numberOfTargets <= 0) {
  320. break;
  321. }
  322. PlayerAnimationEvent armswing = new PlayerAnimationEvent(attacker);
  323. mcMMO.p.getServer().getPluginManager().callEvent(armswing);
  324. if (entity instanceof Player) {
  325. Player defender = (Player) entity;
  326. if (!target.getWorld().getPVP()) {
  327. continue;
  328. }
  329. if (defender.getName().equals(attacker.getName())) {
  330. continue;
  331. }
  332. if (PartyManager.getInstance().inSameParty(attacker, defender)) {
  333. continue;
  334. }
  335. PlayerProfile playerProfile = Users.getProfile((Player) entity);
  336. if (playerProfile.getGodMode()) {
  337. continue;
  338. }
  339. }
  340. else if (entity instanceof Tameable) {
  341. AnimalTamer tamer = ((Tameable) entity).getOwner();
  342. if (tamer instanceof Player) {
  343. if (tamer.equals(attacker) || PartyManager.getInstance().inSameParty(attacker, (Player) tamer)) {
  344. continue;
  345. }
  346. }
  347. }
  348. switch (type) {
  349. case SWORDS:
  350. if (entity instanceof Player) {
  351. ((Player) entity).sendMessage(LocaleLoader.getString("Swords.Combat.SS.Struck"));
  352. }
  353. BleedTimer.add((LivingEntity) entity, 5);
  354. break;
  355. case AXES:
  356. if (entity instanceof Player) {
  357. ((Player) entity).sendMessage(LocaleLoader.getString("Axes.Combat.Cleave.Struck"));
  358. }
  359. break;
  360. default:
  361. break;
  362. }
  363. dealDamage((LivingEntity) entity, damageAmount, attacker);
  364. numberOfTargets--;
  365. }
  366. }
  367. /**
  368. * Start the task that gives combat XP.
  369. *
  370. * @param attacker The attacking player
  371. * @param PP The player's PlayerProfile
  372. * @param target The defending entity
  373. * @param skillType The skill being used
  374. */
  375. public static void startGainXp(Player attacker, PlayerProfile PP, LivingEntity target, SkillType skillType) {
  376. double baseXP = 0;
  377. if (target instanceof Player) {
  378. if (!configInstance.getExperienceGainsPlayerVersusPlayerEnabled()) {
  379. return;
  380. }
  381. Player defender = (Player) target;
  382. if (System.currentTimeMillis() >= Users.getProfile(defender).getRespawnATS() + 5) {
  383. baseXP = 20 * configInstance.getPlayerVersusPlayerXP();
  384. }
  385. }
  386. else if (!target.hasMetadata("mcmmoFromMobSpawner")) {
  387. if (target instanceof Animals && !target.hasMetadata("mcmmoSummoned")) {
  388. baseXP = configInstance.getAnimalsXP();
  389. }
  390. else {
  391. EntityType type = target.getType();
  392. switch (type) {
  393. case BLAZE:
  394. baseXP = configInstance.getBlazeXP();
  395. break;
  396. case CAVE_SPIDER:
  397. baseXP = configInstance.getCaveSpiderXP();
  398. break;
  399. case CREEPER:
  400. baseXP = configInstance.getCreeperXP();
  401. break;
  402. case ENDER_DRAGON:
  403. baseXP = configInstance.getEnderDragonXP();
  404. break;
  405. case ENDERMAN:
  406. baseXP = configInstance.getEndermanXP();
  407. break;
  408. case GHAST:
  409. baseXP = configInstance.getGhastXP();
  410. break;
  411. case MAGMA_CUBE:
  412. baseXP = configInstance.getMagmaCubeXP();
  413. break;
  414. case IRON_GOLEM:
  415. if (!((IronGolem) target).isPlayerCreated()) {
  416. baseXP = configInstance.getIronGolemXP();
  417. }
  418. break;
  419. case PIG_ZOMBIE:
  420. baseXP = configInstance.getPigZombieXP();
  421. break;
  422. case SILVERFISH:
  423. baseXP = configInstance.getSilverfishXP();
  424. break;
  425. case SKELETON:
  426. baseXP = configInstance.getSkeletonXP();
  427. break;
  428. case SLIME:
  429. baseXP = configInstance.getSlimeXP();
  430. break;
  431. case SPIDER:
  432. baseXP = configInstance.getSpiderXP();
  433. break;
  434. case ZOMBIE:
  435. baseXP = configInstance.getZombieXP();
  436. break;
  437. default:
  438. break;
  439. }
  440. }
  441. baseXP *= 10;
  442. }
  443. if (baseXP != 0) {
  444. mcMMO.p.getServer().getScheduler().scheduleSyncDelayedTask(mcMMO.p, new GainXp(attacker, PP, skillType, baseXP, target), 0);
  445. }
  446. }
  447. }