/** * @param Vector3 $pos1 * @param Vector3 $pos2 * * @return MovingObjectPosition */ public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) { $bb = $this->getBoundingBox(); if ($bb === null) { return null; } $v1 = $pos1->getIntermediateWithXValue($pos2, $bb->minX); $v2 = $pos1->getIntermediateWithXValue($pos2, $bb->maxX); $v3 = $pos1->getIntermediateWithYValue($pos2, $bb->minY); $v4 = $pos1->getIntermediateWithYValue($pos2, $bb->maxY); $v5 = $pos1->getIntermediateWithZValue($pos2, $bb->minZ); $v6 = $pos1->getIntermediateWithZValue($pos2, $bb->maxZ); if ($v1 !== null and !$bb->isVectorInYZ($v1)) { $v1 = null; } if ($v2 !== null and !$bb->isVectorInYZ($v2)) { $v2 = null; } if ($v3 !== null and !$bb->isVectorInXZ($v3)) { $v3 = null; } if ($v4 !== null and !$bb->isVectorInXZ($v4)) { $v4 = null; } if ($v5 !== null and !$bb->isVectorInXY($v5)) { $v5 = null; } if ($v6 !== null and !$bb->isVectorInXY($v6)) { $v6 = null; } $vector = $v1; if ($v2 !== null and ($vector === null or $pos1->distanceSquared($v2) < $pos1->distanceSquared($vector))) { $vector = $v2; } if ($v3 !== null and ($vector === null or $pos1->distanceSquared($v3) < $pos1->distanceSquared($vector))) { $vector = $v3; } if ($v4 !== null and ($vector === null or $pos1->distanceSquared($v4) < $pos1->distanceSquared($vector))) { $vector = $v4; } if ($v5 !== null and ($vector === null or $pos1->distanceSquared($v5) < $pos1->distanceSquared($vector))) { $vector = $v5; } if ($v6 !== null and ($vector === null or $pos1->distanceSquared($v6) < $pos1->distanceSquared($vector))) { $vector = $v6; } if ($vector === null) { return null; } $f = -1; if ($vector === $v1) { $f = 4; } elseif ($vector === $v2) { $f = 5; } elseif ($vector === $v3) { $f = 0; } elseif ($vector === $v4) { $f = 1; } elseif ($vector === $v5) { $f = 2; } elseif ($vector === $v6) { $f = 3; } return MovingObjectPosition::fromBlock($this->x, $this->y, $this->z, $f, $vector->add($this->x, $this->y, $this->z)); }
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 calculateIntercept(Vector3 $pos1, Vector3 $pos2) { $intermediateVectors = $this->getIntermediateVectorsArray($pos1, $pos2); $vector = $this->calculateInterceptVector($pos1, $intermediateVectors); if ($vector === null) { return null; } $f = $this->calculateInterceptSide($vector, $intermediateVectors); return MovingObjectPosition::fromBlock(0, 0, 0, $f, $vector); }
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; }
/** * @param Vector3 $pos1 * @param Vector3 $pos2 * * @return MovingObjectPosition */ public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) { $bb = $this->getBoundingBox(); if ($bb === null) { return null; } $intermediateVectors = $bb->getIntermediateVectorsArray($pos1, $pos2); $vector = $bb->calculateInterceptVector($pos1, $intermediateVectors); if ($vector === null) { return null; } $f = $bb->calculateInterceptSide($vector, $intermediateVectors); return MovingObjectPosition::fromBlock($this->x, $this->y, $this->z, $f, $vector->add($this->x, $this->y, $this->z)); }