public function onUpdate($currentTick) { if ($this->closed) { return false; } $tickDiff = $currentTick - $this->lastUpdate; if ($tickDiff <= 0 and !$this->justCreated) { return true; } $this->lastUpdate = $currentTick; $hasUpdate = $this->entityBaseTick($tickDiff); if ($this->isAlive()) { $movingObjectPosition = null; if (!$this->isCollided) { $this->motionY -= $this->gravity; } $moveVector = new Vector3($this->x + $this->motionX, $this->y + $this->motionY, $this->z + $this->motionZ); $list = $this->getLevel()->getCollidingEntities($this->boundingBox->addCoord($this->motionX, $this->motionY, $this->motionZ)->expand(1, 1, 1), $this); $nearDistance = PHP_INT_MAX; $nearEntity = null; foreach ($list as $entity) { if ($entity === $this->shootingEntity and $this->ticksLived < 5) { continue; } $axisalignedbb = $entity->boundingBox->grow(0.3, 0.3, 0.3); $ob = $axisalignedbb->calculateIntercept($this, $moveVector); if ($ob === null) { continue; } $distance = $this->distanceSquared($ob->hitVector); if ($distance < $nearDistance) { $nearDistance = $distance; $nearEntity = $entity; } } if ($nearEntity !== null) { $movingObjectPosition = MovingObjectPosition::fromEntity($nearEntity); } if ($movingObjectPosition !== null) { if ($movingObjectPosition->entityHit !== null) { $this->server->getPluginManager()->callEvent(new ProjectileHitEvent($this)); $motion = sqrt($this->motionX ** 2 + $this->motionY ** 2 + $this->motionZ ** 2); $damage = ceil($motion * $this->damage); if ($this instanceof Arrow and $this->isCritical) { $damage += mt_rand(0, (int) ($damage / 2) + 1); } if ($this->shootingEntity === null) { $ev = new EntityDamageByEntityEvent($this, $movingObjectPosition->entityHit, EntityDamageEvent::CAUSE_PROJECTILE, $damage); } else { $ev = new EntityDamageByChildEntityEvent($this->shootingEntity, $this, $movingObjectPosition->entityHit, EntityDamageEvent::CAUSE_PROJECTILE, $damage); } if ($movingObjectPosition->entityHit->attack($ev->getFinalDamage(), $ev) === true) { if ($this instanceof Arrow and $this->getPotionId() != 0) { foreach (Potion::getAdditionalEffects($this->potionId - 1) as $effect) { $movingObjectPosition->entityHit->addEffect($effect->setDuration($effect->getDuration() / 8)); } } #$ev->useArmors(); } $this->hadCollision = true; if ($this->fireTicks > 0) { $ev = new EntityCombustByEntityEvent($this, $movingObjectPosition->entityHit, 5); $this->server->getPluginManager()->callEvent($ev); if (!$ev->isCancelled()) { $movingObjectPosition->entityHit->setOnFire($ev->getDuration()); } } $this->kill(); return true; } } $this->move($this->motionX, $this->motionY, $this->motionZ); if ($this->isCollided and !$this->hadCollision) { $this->hadCollision = true; $this->motionX = 0; $this->motionY = 0; $this->motionZ = 0; $this->server->getPluginManager()->callEvent(new ProjectileHitEvent($this)); } elseif (!$this->isCollided and $this->hadCollision) { $this->hadCollision = false; } if (!$this->onGround or abs($this->motionX) > 1.0E-5 or abs($this->motionY) > 1.0E-5 or abs($this->motionZ) > 1.0E-5) { $f = sqrt($this->motionX ** 2 + $this->motionZ ** 2); $this->yaw = atan2($this->motionX, $this->motionZ) * 180 / M_PI; $this->pitch = atan2($this->motionY, $f) * 180 / M_PI; $hasUpdate = true; } $this->updateMovement(); } return $hasUpdate; }