/src/pocketmine/event/entity/EntityDamageEvent.php

https://gitlab.com/Skull3x/Genisys · PHP · 306 lines · 198 code · 29 blank · 79 comment · 20 complexity · 088aea88be6025ae6d41631e60b410d1 MD5 · raw file

  1. <?php
  2. /**
  3. *
  4. * ____ _ _ __ __ _ __ __ ____
  5. * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
  6. * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
  7. * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
  8. * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
  9. *
  10. * This program is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU Lesser General Public License as published by
  12. * the Free Software Foundation, either version 3 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * @author PocketMine Team
  16. * @link http://www.pocketmine.net/
  17. *
  18. *
  19. */
  20. namespace pocketmine\event\entity;
  21. use pocketmine\entity\Effect;
  22. use pocketmine\entity\Entity;
  23. use pocketmine\event\Cancellable;
  24. use pocketmine\inventory\PlayerInventory;
  25. use pocketmine\Player;
  26. use pocketmine\item\Item;
  27. use pocketmine\item\enchantment\enchantment;
  28. class EntityDamageEvent extends EntityEvent implements Cancellable{
  29. public static $handlerList = null;
  30. const MODIFIER_BASE = 0;
  31. const MODIFIER_RESISTANCE = 1;
  32. const MODIFIER_ARMOR = 2;
  33. const MODIFIER_PROTECTION = 3;
  34. const MODIFIER_STRENGTH = 4;
  35. const MODIFIER_WEAKNESS = 5;
  36. const CAUSE_CONTACT = 0;
  37. const CAUSE_ENTITY_ATTACK = 1;
  38. const CAUSE_PROJECTILE = 2;
  39. const CAUSE_SUFFOCATION = 3;
  40. const CAUSE_FALL = 4;
  41. const CAUSE_FIRE = 5;
  42. const CAUSE_FIRE_TICK = 6;
  43. const CAUSE_LAVA = 7;
  44. const CAUSE_DROWNING = 8;
  45. const CAUSE_BLOCK_EXPLOSION = 9;
  46. const CAUSE_ENTITY_EXPLOSION = 10;
  47. const CAUSE_VOID = 11;
  48. const CAUSE_SUICIDE = 12;
  49. const CAUSE_MAGIC = 13;
  50. const CAUSE_CUSTOM = 14;
  51. const CAUSE_STARVATION = 15;
  52. const CAUSE_LIGHTNING = 16;
  53. private $cause;
  54. private $EPF = 0;
  55. private $fireProtectL = 0;
  56. /** @var array */
  57. private $modifiers;
  58. private $ratemodifiers = [];
  59. private $originals;
  60. private $use_armors = [];
  61. /**
  62. * @param Entity $entity
  63. * @param int $cause
  64. * @param int|int[] $damage
  65. *
  66. * @throws \Exception
  67. */
  68. public function __construct(Entity $entity, $cause, $damage){
  69. $this->entity = $entity;
  70. $this->cause = $cause;
  71. if(is_array($damage)){
  72. $this->modifiers = $damage;
  73. }else{
  74. $this->modifiers = [
  75. self::MODIFIER_BASE => $damage
  76. ];
  77. }
  78. $this->originals = $this->modifiers;
  79. if(!isset($this->modifiers[self::MODIFIER_BASE])){
  80. throw new \InvalidArgumentException("BASE Damage modifier missing");
  81. }
  82. //For DAMAGE_RESISTANCE
  83. if($cause !== self::CAUSE_VOID and $cause !== self::CAUSE_SUICIDE){
  84. if($entity->hasEffect(Effect::DAMAGE_RESISTANCE)){
  85. $RES_level = 1 - 0.20 * ($entity->getEffect(Effect::DAMAGE_RESISTANCE)->getAmplifier() + 1);
  86. if($RES_level < 0){
  87. $RES_level = 0;
  88. }
  89. $this->setRateDamage($RES_level, self::MODIFIER_RESISTANCE);
  90. }
  91. }
  92. //TODO: add zombie
  93. if($entity instanceof Player and $entity->getInventory() instanceof PlayerInventory){
  94. switch($cause){
  95. case self::CAUSE_CONTACT:
  96. case self::CAUSE_ENTITY_ATTACK:
  97. case self::CAUSE_PROJECTILE:
  98. case self::CAUSE_FIRE:
  99. case self::CAUSE_LAVA:
  100. case self::CAUSE_BLOCK_EXPLOSION:
  101. case self::CAUSE_ENTITY_EXPLOSION:
  102. case self::CAUSE_LIGHTNING:
  103. $points = 0;
  104. foreach($entity->getInventory()->getArmorContents() as $i){
  105. if($i->isArmor()){
  106. $points += $i->getArmorValue();
  107. }
  108. }
  109. if($points !== 0){
  110. $this->setRateDamage(1 - 0.04 * $points, self::MODIFIER_ARMOR);
  111. $this->use_armors = $entity->getInventory()->getArmorContents();
  112. }
  113. //For Protection
  114. $spe_Prote = null;
  115. switch ($cause){
  116. case self::CAUSE_ENTITY_EXPLOSION:
  117. case self::CAUSE_BLOCK_EXPLOSION:
  118. $spe_Prote = Enchantment::TYPE_ARMOR_EXPLOSION_PROTECTION;
  119. break;
  120. case self::CAUSE_FIRE:
  121. case self::CAUSE_LAVA:
  122. $spe_Prote = Enchantment::TYPE_ARMOR_FIRE_PROTECTION;
  123. break;
  124. case self::CAUSE_PROJECTILE:
  125. $spe_Prote = Enchantment::TYPE_ARMOR_PROJECTILE_PROTECTION;
  126. break;
  127. default;
  128. break;
  129. }
  130. foreach($this->use_armors as $i){
  131. if($i->isArmor()){
  132. $this->EPF += $i->getEnchantmentLevel(Enchantment::TYPE_ARMOR_PROTECTION);
  133. $this->fireProtectL = max($this->fireProtectL, $i->getEnchantmentLevel(Enchantment::TYPE_ARMOR_FIRE_PROTECTION));
  134. if($spe_Prote !== null){
  135. $this->EPF += 2 * $i->getEnchantmentLevel($spe_Prote);
  136. }
  137. }
  138. }
  139. break;
  140. case self::CAUSE_FALL:
  141. //Feather Falling
  142. $i = $entity->getInventory()->getBoots();
  143. if($i->isArmor()){
  144. $this->EPF += $i->getEnchantmentLevel(Enchantment::TYPE_ARMOR_PROTECTION);
  145. $this->EPF += 3 * $i->getEnchantmentLevel(Enchantment::TYPE_ARMOR_FALL_PROTECTION);
  146. }
  147. break;
  148. case self::CAUSE_FIRE_TICK:
  149. case self::CAUSE_SUFFOCATION:
  150. case self::CAUSE_DROWNING:
  151. case self::CAUSE_VOID:
  152. case self::CAUSE_SUICIDE:
  153. case self::CAUSE_MAGIC:
  154. case self::CAUSE_CUSTOM:
  155. case self::CAUSE_STARVATION:
  156. break;
  157. default:
  158. break;
  159. }
  160. if($this->EPF !== 0){
  161. $this->EPF = min(20, ceil($this->EPF * mt_rand(50, 100) / 100));
  162. $this->setRateDamage(1 - 0.04 * $this->EPF, self::MODIFIER_PROTECTION);
  163. }
  164. }
  165. }
  166. /**
  167. * @return int
  168. */
  169. public function getCause(){
  170. return $this->cause;
  171. }
  172. /**
  173. * @param int $type
  174. *
  175. * @return int
  176. */
  177. public function getOriginalDamage($type = self::MODIFIER_BASE){
  178. if(isset($this->originals[$type])){
  179. return $this->originals[$type];
  180. }
  181. return 0;
  182. }
  183. /**
  184. * @param int $type
  185. *
  186. * @return int
  187. */
  188. public function getDamage($type = self::MODIFIER_BASE){
  189. if(isset($this->modifiers[$type])){
  190. return $this->modifiers[$type];
  191. }
  192. return 0;
  193. }
  194. /**
  195. * @param float $damage
  196. * @param int $type
  197. *
  198. * @throws \UnexpectedValueException
  199. */
  200. public function setDamage($damage, $type = self::MODIFIER_BASE){
  201. $this->modifiers[$type] = $damage;
  202. }
  203. /**
  204. * @param int $type
  205. *
  206. * @return float 1 - the percentage
  207. */
  208. public function getRateDamage($type = self::MODIFIER_BASE){
  209. if(isset($this->ratemodifiers[$type])){
  210. return $this->ratemodifiers[$type];
  211. }
  212. return 1;
  213. }
  214. /**
  215. * @param float $damage
  216. * @param int $type
  217. *
  218. * Notice:If you want to add/reduce the damage without reducing by Armor or effect. set a new Damage using setDamage
  219. * Notice:If you want to add/reduce the damage within reducing by Armor of effect. Plz change the MODIFIER_BASE
  220. * Notice:If you want to add/reduce the damage by multiplying. Plz use this function.
  221. */
  222. public function setRateDamage($damage, $type = self::MODIFIER_BASE){
  223. $this->ratemodifiers[$type] = $damage;
  224. }
  225. /**
  226. * @param int $type
  227. *
  228. * @return bool
  229. */
  230. public function isApplicable($type){
  231. return isset($this->modifiers[$type]);
  232. }
  233. /**
  234. * @return int
  235. */
  236. public function getFinalDamage(){
  237. $damage = $this->modifiers[self::MODIFIER_BASE];
  238. foreach($this->ratemodifiers as $type => $d){
  239. $damage *= $d;
  240. }
  241. foreach($this->modifiers as $type => $d){
  242. if($type !== self::MODIFIER_BASE){
  243. $damage += $d;
  244. }
  245. }
  246. return $damage;
  247. }
  248. /**
  249. * @return Item $use_armors
  250. */
  251. public function getUsedArmors(){
  252. return $this->use_armors;
  253. }
  254. /**
  255. * @return Int $fireProtectL
  256. */
  257. public function getFireProtectL(){
  258. return $this->fireProtectL;
  259. }
  260. /**
  261. * @return bool
  262. */
  263. public function useArmors(){
  264. if($this->entity instanceof Player){
  265. if($this->entity->isSurvival() and $this->entity->isAlive()){
  266. foreach ($this->use_armors as $index=>$i){
  267. if($i->isArmor()){
  268. $i->useOn($i);
  269. $this->entity->getInventory()->setArmorItem($index, $i);
  270. }
  271. }
  272. }
  273. return true;
  274. }
  275. return false;
  276. }
  277. }