public function onUpdate() { $this->entityBaseTick(); if ($this->closed !== false) { return false; } $movingObjectPosition = null; $this->motionY -= $this->gravity; $this->inBlock = $this->checkObstruction($this->x, ($this->boundingBox->minY + $this->boundingBox->maxY) / 2, $this->z); $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->canCollideWith($this) or $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->distance($ob->hitVector); if ($distance < $nearDistance) { $nearDistance = $distance; $nearEntity = $entity; } } if ($nearEntity !== null) { $movingObjectPosition = MovingObjectPosition::fromEntity($nearEntity); } if ($movingObjectPosition !== null) { if ($movingObjectPosition->entityHit !== null) { $motion = sqrt($this->motionX ** 2 + $this->motionY ** 2 + $this->motionZ ** 2); $damage = ceil($motion * $this->damage); $ev = new EntityDamageByEntityEvent($this->shootingEntity === null ? $this : $this->shootingEntity, $movingObjectPosition->entityHit, EntityDamageEvent::CAUSE_PROJECTILE, $damage); $this->server->getPluginManager()->callEvent($ev); if (!$ev->isCancelled()) { $movingObjectPosition->entityHit->attack($damage, $ev); if ($this->fireTicks > 0) { $movingObjectPosition->entityHit->setOnFire(5); } $this->kill(); } } } $this->move($this->motionX, $this->motionY, $this->motionZ); $friction = 1 - $this->drag; if ($this->onGround) { $friction = $this->getLevel()->getBlock(new Vector3($this->getFloorX(), $this->getFloorY() - 1, $this->getFloorZ()))->frictionFactor * $friction; } $this->motionX *= $friction; $this->motionY *= 1 - $this->drag; $this->motionZ *= $friction; if ($this->onGround) { $this->motionX = 0; $this->motionY = 0; $this->motionZ = 0; } if ($this->motionX != 0 or $this->motionY != 0 or $this->motionZ != 0) { $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; } if ($this->age > 1200) { $this->kill(); } $this->updateMovement(); return !$this->onGround or $this->motionX == 0 and $this->motionY == 0 and $this->motionZ == 0; }
public function onUpdate($currentTick) { if ($this->closed) { return false; } $tickDiff = max(1, $currentTick - $this->lastUpdate); $this->lastUpdate = $currentTick; $hasUpdate = $this->entityBaseTick($tickDiff); if (!$this->dead) { $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); } $movingObjectPosition->entityHit->attack($ev->getFinalDamage(), $ev); $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 $this->motionX != 0 or $this->motionY != 0 or $this->motionZ != 0) { $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; }