setPotionId($this->namedtag->getShort("PotionId", 0)); } public function saveNBT() : void{ parent::saveNBT(); $this->namedtag->setShort("PotionId", $this->getPotionId()); } public function getResultDamage() : int{ return -1; //no damage } protected function onHit(ProjectileHitEvent $event) : void{ $effects = $this->getPotionEffects(); $hasEffects = true; if(empty($effects)){ $colors = [ new Color(0x38, 0x5d, 0xc6) //Default colour for splash water bottle and similar with no effects. ]; $hasEffects = false; }else{ $colors = []; foreach($effects as $effect){ $level = $effect->getEffectLevel(); for($j = 0; $j < $level; ++$j){ $colors[] = $effect->getColor(); } } } $this->level->broadcastLevelEvent($this, LevelEventPacket::EVENT_PARTICLE_SPLASH, Color::mix(...$colors)->toARGB()); $this->level->broadcastLevelSoundEvent($this, LevelSoundEventPacket::SOUND_GLASS); if($hasEffects){ if(!$this->willLinger()){ foreach($this->level->getNearbyEntities($this->boundingBox->expandedCopy(4.125, 2.125, 4.125), $this) as $entity){ if($entity instanceof Living and $entity->isAlive()){ $distanceSquared = $entity->distanceSquared($this); if($distanceSquared > 16){ //4 blocks continue; } $distanceMultiplier = 1 - (sqrt($distanceSquared) / 4); if($event instanceof ProjectileHitEntityEvent and $entity === $event->getEntityHit()){ $distanceMultiplier = 1.0; } foreach($this->getPotionEffects() as $effect){ //getPotionEffects() is used to get COPIES to avoid accidentally modifying the same effect instance already applied to another entity if(!$effect->getType()->isInstantEffect()){ $newDuration = (int) round($effect->getDuration() * 0.75 * $distanceMultiplier); if($newDuration < 20){ continue; } $effect->setDuration($newDuration); $entity->addEffect($effect); }else{ $effect->getType()->applyEffect($entity, $effect, $distanceMultiplier, $this, $this->getOwningEntity()); } } } } }else{ //TODO: lingering potions } }elseif($event instanceof ProjectileHitBlockEvent and $this->getPotionId() === Potion::WATER){ $blockIn = $event->getBlockHit()->getSide($event->getRayTraceResult()->getHitFace()); if($blockIn->getId() === Block::FIRE){ $this->level->setBlock($blockIn, BlockFactory::get(Block::AIR)); } foreach($blockIn->getHorizontalSides() as $horizontalSide){ if($horizontalSide->getId() === Block::FIRE){ $this->level->setBlock($horizontalSide, BlockFactory::get(Block::AIR)); } } } } /** * Returns the meta value of the potion item that this splash potion corresponds to. This decides what effects will be applied to the entity when it collides with its target. * @return int */ public function getPotionId() : int{ return $this->propertyManager->getShort(self::DATA_POTION_AUX_VALUE) ?? 0; } /** * @param int $id */ public function setPotionId(int $id) : void{ $this->propertyManager->setShort(self::DATA_POTION_AUX_VALUE, $id); } /** * Returns whether this splash potion will create an area-effect cloud when it lands. * @return bool */ public function willLinger() : bool{ return $this->getDataFlag(self::DATA_FLAGS, self::DATA_FLAG_LINGER); } /** * Sets whether this splash potion will create an area-effect-cloud when it lands. * * @param bool $value */ public function setLinger(bool $value = true) : void{ $this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_LINGER, $value); } /** * @return EffectInstance[] */ public function getPotionEffects() : array{ return Potion::getPotionEffectsById($this->getPotionId()); } }