From acf29711c2c8039d8da115ff250be9870e72af19 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 23 May 2018 10:05:01 +0100 Subject: [PATCH] Implemented Totems, close #2198 Totem usage can be detected using the MODIFIER_TOTEM constant of EntityDamageEvent. This does not currently support using the totem in the offhand because offhand is not implemented yet. --- src/pocketmine/entity/Human.php | 37 +++++++++++++++++++ .../event/entity/EntityDamageEvent.php | 1 + src/pocketmine/item/ItemFactory.php | 2 +- src/pocketmine/item/Totem.php | 34 +++++++++++++++++ 4 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/pocketmine/item/Totem.php diff --git a/src/pocketmine/entity/Human.php b/src/pocketmine/entity/Human.php index 2c97c42e7f..af35ef6348 100644 --- a/src/pocketmine/entity/Human.php +++ b/src/pocketmine/entity/Human.php @@ -35,6 +35,7 @@ use pocketmine\inventory\PlayerInventory; use pocketmine\item\Consumable; use pocketmine\item\FoodSource; use pocketmine\item\Item; +use pocketmine\item\Totem; use pocketmine\level\Level; use pocketmine\nbt\NBT; use pocketmine\nbt\tag\ByteArrayTag; @@ -43,6 +44,7 @@ use pocketmine\nbt\tag\IntTag; use pocketmine\nbt\tag\ListTag; use pocketmine\nbt\tag\StringTag; use pocketmine\network\mcpe\protocol\AddPlayerPacket; +use pocketmine\network\mcpe\protocol\EntityEventPacket; use pocketmine\network\mcpe\protocol\LevelEventPacket; use pocketmine\network\mcpe\protocol\LevelSoundEventPacket; use pocketmine\network\mcpe\protocol\PlayerSkinPacket; @@ -673,6 +675,41 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ return $this->getNameTag(); } + public function applyDamageModifiers(EntityDamageEvent $source) : void{ + parent::applyDamageModifiers($source); + + $type = $source->getCause(); + if($type !== EntityDamageEvent::CAUSE_SUICIDE and $type !== EntityDamageEvent::CAUSE_VOID + and $this->inventory->getItemInHand() instanceof Totem){ //TODO: check offhand as well (when it's implemented) + + $compensation = $this->getHealth() - $source->getFinalDamage() - 1; + if($compensation < 0){ + $source->setModifier($compensation, EntityDamageEvent::MODIFIER_TOTEM); + } + } + } + + protected function applyPostDamageEffects(EntityDamageEvent $source) : void{ + parent::applyPostDamageEffects($source); + $totemModifier = $source->getModifier(EntityDamageEvent::MODIFIER_TOTEM); + if($totemModifier < 0){ //Totem prevented death + $this->removeAllEffects(); + + $this->addEffect(new EffectInstance(Effect::getEffect(Effect::REGENERATION), 40 * 20, 1)); + $this->addEffect(new EffectInstance(Effect::getEffect(Effect::FIRE_RESISTANCE), 40 * 20, 1)); + $this->addEffect(new EffectInstance(Effect::getEffect(Effect::ABSORPTION), 5 * 20, 1)); + + $this->broadcastEntityEvent(EntityEventPacket::CONSUME_TOTEM); + $this->level->broadcastLevelEvent($this->add(0, $this->eyeHeight, 0), LevelEventPacket::EVENT_SOUND_TOTEM); + + $hand = $this->inventory->getItemInHand(); + if($hand instanceof Totem){ + $hand->pop(); //Plugins could alter max stack size + $this->inventory->setItemInHand($hand); + } + } + } + public function getDrops() : array{ return array_merge( $this->inventory !== null ? array_values($this->inventory->getContents()) : [], diff --git a/src/pocketmine/event/entity/EntityDamageEvent.php b/src/pocketmine/event/entity/EntityDamageEvent.php index bee56fae7c..aa4d5d06c9 100644 --- a/src/pocketmine/event/entity/EntityDamageEvent.php +++ b/src/pocketmine/event/entity/EntityDamageEvent.php @@ -37,6 +37,7 @@ class EntityDamageEvent extends EntityEvent implements Cancellable{ public const MODIFIER_ABSORPTION = 5; public const MODIFIER_ARMOR_ENCHANTMENTS = 6; public const MODIFIER_CRITICAL = 7; + public const MODIFIER_TOTEM = 8; public const CAUSE_CONTACT = 0; public const CAUSE_ENTITY_ATTACK = 1; diff --git a/src/pocketmine/item/ItemFactory.php b/src/pocketmine/item/ItemFactory.php index d6b5e0cda7..f687b38b8b 100644 --- a/src/pocketmine/item/ItemFactory.php +++ b/src/pocketmine/item/ItemFactory.php @@ -228,7 +228,7 @@ class ItemFactory{ self::registerItem(new Item(Item::SHULKER_SHELL, 0, "Shulker Shell")); self::registerItem(new Banner()); - //TODO: TOTEM + self::registerItem(new Totem()); self::registerItem(new Item(Item::IRON_NUGGET, 0, "Iron Nugget")); diff --git a/src/pocketmine/item/Totem.php b/src/pocketmine/item/Totem.php new file mode 100644 index 0000000000..f64ced723b --- /dev/null +++ b/src/pocketmine/item/Totem.php @@ -0,0 +1,34 @@ +